aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-02-16 20:13:02 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-02-16 20:13:02 +0000
commitb60736ec1405bb0a8dd40989f67ef4c93da068ab (patch)
tree5c43fbb7c9fc45f0f87e0e6795a86267dbd12f9d /clang/lib/Sema
parentcfca06d7963fa0909f90483b42a6d7d194d01e08 (diff)
downloadsrc-b60736ec1405bb0a8dd40989f67ef4c93da068ab.tar.gz
src-b60736ec1405bb0a8dd40989f67ef4c93da068ab.zip
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/AnalysisBasedWarnings.cpp102
-rw-r--r--clang/lib/Sema/CodeCompleteConsumer.cpp6
-rw-r--r--clang/lib/Sema/DeclSpec.cpp167
-rw-r--r--clang/lib/Sema/JumpDiagnostics.cpp17
-rw-r--r--clang/lib/Sema/MultiplexExternalSemaSource.cpp7
-rw-r--r--clang/lib/Sema/ScopeInfo.cpp1
-rw-r--r--clang/lib/Sema/Sema.cpp163
-rw-r--r--clang/lib/Sema/SemaAccess.cpp3
-rw-r--r--clang/lib/Sema/SemaAttr.cpp345
-rw-r--r--clang/lib/Sema/SemaCUDA.cpp103
-rw-r--r--clang/lib/Sema/SemaCast.cpp81
-rw-r--r--clang/lib/Sema/SemaChecking.cpp1029
-rw-r--r--clang/lib/Sema/SemaCodeComplete.cpp90
-rw-r--r--clang/lib/Sema/SemaConcept.cpp23
-rw-r--r--clang/lib/Sema/SemaCoroutine.cpp100
-rw-r--r--clang/lib/Sema/SemaDecl.cpp1181
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp1060
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp225
-rw-r--r--clang/lib/Sema/SemaDeclObjC.cpp76
-rw-r--r--clang/lib/Sema/SemaExceptionSpec.cpp4
-rw-r--r--clang/lib/Sema/SemaExpr.cpp1006
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp201
-rw-r--r--clang/lib/Sema/SemaExprMember.cpp119
-rw-r--r--clang/lib/Sema/SemaExprObjC.cpp88
-rw-r--r--clang/lib/Sema/SemaInit.cpp356
-rw-r--r--clang/lib/Sema/SemaLambda.cpp145
-rw-r--r--clang/lib/Sema/SemaLookup.cpp378
-rw-r--r--clang/lib/Sema/SemaModule.cpp2
-rw-r--r--clang/lib/Sema/SemaObjCProperty.cpp14
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp1065
-rw-r--r--clang/lib/Sema/SemaOverload.cpp978
-rw-r--r--clang/lib/Sema/SemaSYCL.cpp20
-rw-r--r--clang/lib/Sema/SemaStmt.cpp217
-rw-r--r--clang/lib/Sema/SemaStmtAsm.cpp6
-rw-r--r--clang/lib/Sema/SemaStmtAttr.cpp78
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp637
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp379
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp187
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp421
-rw-r--r--clang/lib/Sema/SemaTemplateVariadic.cpp63
-rw-r--r--clang/lib/Sema/SemaType.cpp1220
-rw-r--r--clang/lib/Sema/TreeTransform.h205
-rw-r--r--clang/lib/Sema/UsedDeclVisitor.h11
43 files changed, 8271 insertions, 4308 deletions
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 3b7356893833..edd9742ed207 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -24,6 +24,7 @@
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
+#include "clang/Analysis/Analyses/CalledOnceCheck.h"
#include "clang/Analysis/Analyses/Consumed.h"
#include "clang/Analysis/Analyses/ReachableCode.h"
#include "clang/Analysis/Analyses/ThreadSafety.h"
@@ -36,6 +37,7 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallString.h"
@@ -1623,6 +1625,82 @@ private:
});
}
};
+
+class CalledOnceCheckReporter : public CalledOnceCheckHandler {
+public:
+ CalledOnceCheckReporter(Sema &S) : S(S) {}
+ void handleDoubleCall(const ParmVarDecl *Parameter, const Expr *Call,
+ const Expr *PrevCall, bool IsCompletionHandler,
+ bool Poised) override {
+ auto DiagToReport = IsCompletionHandler
+ ? diag::warn_completion_handler_called_twice
+ : diag::warn_called_once_gets_called_twice;
+ S.Diag(Call->getBeginLoc(), DiagToReport) << Parameter;
+ S.Diag(PrevCall->getBeginLoc(), diag::note_called_once_gets_called_twice)
+ << Poised;
+ }
+
+ void handleNeverCalled(const ParmVarDecl *Parameter,
+ bool IsCompletionHandler) override {
+ auto DiagToReport = IsCompletionHandler
+ ? diag::warn_completion_handler_never_called
+ : diag::warn_called_once_never_called;
+ S.Diag(Parameter->getBeginLoc(), DiagToReport)
+ << Parameter << /* Captured */ false;
+ }
+
+ void handleNeverCalled(const ParmVarDecl *Parameter, const Stmt *Where,
+ NeverCalledReason Reason, bool IsCalledDirectly,
+ bool IsCompletionHandler) override {
+ auto DiagToReport = IsCompletionHandler
+ ? diag::warn_completion_handler_never_called_when
+ : diag::warn_called_once_never_called_when;
+ S.Diag(Where->getBeginLoc(), DiagToReport)
+ << Parameter << IsCalledDirectly << (unsigned)Reason;
+ }
+
+ void handleCapturedNeverCalled(const ParmVarDecl *Parameter,
+ const Decl *Where,
+ bool IsCompletionHandler) override {
+ auto DiagToReport = IsCompletionHandler
+ ? diag::warn_completion_handler_never_called
+ : diag::warn_called_once_never_called;
+ S.Diag(Where->getBeginLoc(), DiagToReport)
+ << Parameter << /* Captured */ true;
+ }
+
+private:
+ Sema &S;
+};
+
+constexpr unsigned CalledOnceWarnings[] = {
+ diag::warn_called_once_never_called,
+ diag::warn_called_once_never_called_when,
+ diag::warn_called_once_gets_called_twice};
+
+constexpr unsigned CompletionHandlerWarnings[]{
+ diag::warn_completion_handler_never_called,
+ diag::warn_completion_handler_never_called_when,
+ diag::warn_completion_handler_called_twice};
+
+bool shouldAnalyzeCalledOnceImpl(llvm::ArrayRef<unsigned> DiagIDs,
+ const DiagnosticsEngine &Diags,
+ SourceLocation At) {
+ return llvm::any_of(DiagIDs, [&Diags, At](unsigned DiagID) {
+ return !Diags.isIgnored(DiagID, At);
+ });
+}
+
+bool shouldAnalyzeCalledOnceConventions(const DiagnosticsEngine &Diags,
+ SourceLocation At) {
+ return shouldAnalyzeCalledOnceImpl(CompletionHandlerWarnings, Diags, At);
+}
+
+bool shouldAnalyzeCalledOnceParameters(const DiagnosticsEngine &Diags,
+ SourceLocation At) {
+ return shouldAnalyzeCalledOnceImpl(CalledOnceWarnings, Diags, At) ||
+ shouldAnalyzeCalledOnceConventions(Diags, At);
+}
} // anonymous namespace
namespace clang {
@@ -1849,8 +1927,8 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
<< *PossibleMatch);
if (Verbose && POK == POK_VarAccess) {
PartialDiagnosticAt VNote(D->getLocation(),
- S.PDiag(diag::note_guarded_by_declared_here)
- << D->getNameAsString());
+ S.PDiag(diag::note_guarded_by_declared_here)
+ << D->getDeclName());
Warnings.emplace_back(std::move(Warning), getNotes(Note, VNote));
} else
Warnings.emplace_back(std::move(Warning), getNotes(Note));
@@ -1892,6 +1970,13 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
Warnings.emplace_back(std::move(Warning), getNotes());
}
+ void handleNegativeNotHeld(const NamedDecl *D, Name LockName,
+ SourceLocation Loc) override {
+ PartialDiagnosticAt Warning(
+ Loc, S.PDiag(diag::warn_fun_requires_negative_cap) << D << LockName);
+ Warnings.emplace_back(std::move(Warning), getNotes());
+ }
+
void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName,
SourceLocation Loc) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_fun_excludes_mutex)
@@ -2089,7 +2174,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
if (cast<DeclContext>(D)->isDependentContext())
return;
- if (Diags.hasUncompilableErrorOccurred()) {
+ if (S.hasUncompilableErrorOccurred()) {
// Flush out any possibly unreachable diagnostics.
flushDiagnostics(S, fscope);
return;
@@ -2257,6 +2342,17 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
}
}
+ // Check for violations of "called once" parameter properties.
+ if (S.getLangOpts().ObjC &&
+ shouldAnalyzeCalledOnceParameters(Diags, D->getBeginLoc())) {
+ if (AC.getCFG()) {
+ CalledOnceCheckReporter Reporter(S);
+ checkCalledOnceParameters(
+ AC, Reporter,
+ shouldAnalyzeCalledOnceConventions(Diags, D->getBeginLoc()));
+ }
+ }
+
bool FallThroughDiagFull =
!Diags.isIgnored(diag::warn_unannotated_fallthrough, D->getBeginLoc());
bool FallThroughDiagPerFunction = !Diags.isIgnored(
diff --git a/clang/lib/Sema/CodeCompleteConsumer.cpp b/clang/lib/Sema/CodeCompleteConsumer.cpp
index f1ad8aeaacbb..678a09ba1003 100644
--- a/clang/lib/Sema/CodeCompleteConsumer.cpp
+++ b/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -356,8 +356,7 @@ const char *CodeCompletionAllocator::CopyString(const Twine &String) {
}
StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) {
- const NamedDecl *ND = dyn_cast<NamedDecl>(DC);
- if (!ND)
+ if (!isa<NamedDecl>(DC))
return {};
// Check whether we've already cached the parent name.
@@ -470,8 +469,7 @@ void CodeCompletionBuilder::addParentContext(const DeclContext *DC) {
if (DC->isFunctionOrMethod())
return;
- const NamedDecl *ND = dyn_cast<NamedDecl>(DC);
- if (!ND)
+ if (!isa<NamedDecl>(DC))
return;
ParentName = getCodeCompletionTUInfo().getParentName(DC);
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index f4c30c90ad27..da42db3e8f7b 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -181,6 +181,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
SourceLocation LocalRangeEnd,
Declarator &TheDeclarator,
TypeResult TrailingReturnType,
+ SourceLocation
+ TrailingReturnTypeLoc,
DeclSpec *MethodQualifiers) {
assert(!(MethodQualifiers && MethodQualifiers->getTypeQualifiers() & DeclSpec::TQ_atomic) &&
"function cannot have _Atomic qualifier");
@@ -189,27 +191,29 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
I.Kind = Function;
I.Loc = LocalRangeBegin;
I.EndLoc = LocalRangeEnd;
+ new (&I.Fun) FunctionTypeInfo;
I.Fun.hasPrototype = hasProto;
I.Fun.isVariadic = EllipsisLoc.isValid();
I.Fun.isAmbiguous = isAmbiguous;
- I.Fun.LParenLoc = LParenLoc.getRawEncoding();
- I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding();
- I.Fun.RParenLoc = RParenLoc.getRawEncoding();
+ I.Fun.LParenLoc = LParenLoc;
+ I.Fun.EllipsisLoc = EllipsisLoc;
+ I.Fun.RParenLoc = RParenLoc;
I.Fun.DeleteParams = false;
I.Fun.NumParams = NumParams;
I.Fun.Params = nullptr;
I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef;
- I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding();
- I.Fun.MutableLoc = MutableLoc.getRawEncoding();
+ I.Fun.RefQualifierLoc = RefQualifierLoc;
+ I.Fun.MutableLoc = MutableLoc;
I.Fun.ExceptionSpecType = ESpecType;
- I.Fun.ExceptionSpecLocBeg = ESpecRange.getBegin().getRawEncoding();
- I.Fun.ExceptionSpecLocEnd = ESpecRange.getEnd().getRawEncoding();
+ I.Fun.ExceptionSpecLocBeg = ESpecRange.getBegin();
+ I.Fun.ExceptionSpecLocEnd = ESpecRange.getEnd();
I.Fun.NumExceptionsOrDecls = 0;
I.Fun.Exceptions = nullptr;
I.Fun.NoexceptExpr = nullptr;
I.Fun.HasTrailingReturnType = TrailingReturnType.isUsable() ||
TrailingReturnType.isInvalid();
I.Fun.TrailingReturnType = TrailingReturnType.get();
+ I.Fun.TrailingReturnTypeLoc = TrailingReturnTypeLoc;
I.Fun.MethodQualifiers = nullptr;
I.Fun.QualAttrFactory = nullptr;
@@ -405,7 +409,7 @@ bool Declarator::isDeclarationOfFunction() const {
}
bool Declarator::isStaticMember() {
- assert(getContext() == DeclaratorContext::MemberContext);
+ assert(getContext() == DeclaratorContext::Member);
return getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
(getName().Kind == UnqualifiedIdKind::IK_OperatorFunctionId &&
CXXMethodDecl::isStaticOverloadedOperator(
@@ -499,12 +503,16 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TSCS S) {
llvm_unreachable("Unknown typespec!");
}
-const char *DeclSpec::getSpecifierName(TSW W) {
+const char *DeclSpec::getSpecifierName(TypeSpecifierWidth W) {
switch (W) {
- case TSW_unspecified: return "unspecified";
- case TSW_short: return "short";
- case TSW_long: return "long";
- case TSW_longlong: return "long long";
+ case TypeSpecifierWidth::Unspecified:
+ return "unspecified";
+ case TypeSpecifierWidth::Short:
+ return "short";
+ case TypeSpecifierWidth::Long:
+ return "long";
+ case TypeSpecifierWidth::LongLong:
+ return "long long";
}
llvm_unreachable("Unknown typespec!");
}
@@ -518,12 +526,14 @@ const char *DeclSpec::getSpecifierName(TSC C) {
llvm_unreachable("Unknown typespec!");
}
-
-const char *DeclSpec::getSpecifierName(TSS S) {
+const char *DeclSpec::getSpecifierName(TypeSpecifierSign S) {
switch (S) {
- case TSS_unspecified: return "unspecified";
- case TSS_signed: return "signed";
- case TSS_unsigned: return "unsigned";
+ case TypeSpecifierSign::Unspecified:
+ return "unspecified";
+ case TypeSpecifierSign::Signed:
+ return "signed";
+ case TypeSpecifierSign::Unsigned:
+ return "unsigned";
}
llvm_unreachable("Unknown typespec!");
}
@@ -579,10 +589,14 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
const char *DeclSpec::getSpecifierName(ConstexprSpecKind C) {
switch (C) {
- case CSK_unspecified: return "unspecified";
- case CSK_constexpr: return "constexpr";
- case CSK_consteval: return "consteval";
- case CSK_constinit: return "constinit";
+ case ConstexprSpecKind::Unspecified:
+ return "unspecified";
+ case ConstexprSpecKind::Constexpr:
+ return "constexpr";
+ case ConstexprSpecKind::Consteval:
+ return "consteval";
+ case ConstexprSpecKind::Constinit:
+ return "constinit";
}
llvm_unreachable("Unknown ConstexprSpecKind");
}
@@ -675,18 +689,18 @@ bool DeclSpec::SetStorageClassSpecThread(TSCS TSC, SourceLocation Loc,
/// These methods set the specified attribute of the DeclSpec, but return true
/// and ignore the request if invalid (e.g. "extern" then "auto" is
/// specified).
-bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc,
- const char *&PrevSpec,
- unsigned &DiagID,
+bool DeclSpec::SetTypeSpecWidth(TypeSpecifierWidth W, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
const PrintingPolicy &Policy) {
// Overwrite TSWRange.Begin only if TypeSpecWidth was unspecified, so that
// for 'long long' we will keep the source location of the first 'long'.
- if (TypeSpecWidth == TSW_unspecified)
+ if (getTypeSpecWidth() == TypeSpecifierWidth::Unspecified)
TSWRange.setBegin(Loc);
// Allow turning long -> long long.
- else if (W != TSW_longlong || TypeSpecWidth != TSW_long)
- return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID);
- TypeSpecWidth = W;
+ else if (W != TypeSpecifierWidth::LongLong ||
+ getTypeSpecWidth() != TypeSpecifierWidth::Long)
+ return BadSpecifier(W, getTypeSpecWidth(), PrevSpec, DiagID);
+ TypeSpecWidth = static_cast<unsigned>(W);
// Remember location of the last 'long'
TSWRange.setEnd(Loc);
return false;
@@ -702,12 +716,11 @@ bool DeclSpec::SetTypeSpecComplex(TSC C, SourceLocation Loc,
return false;
}
-bool DeclSpec::SetTypeSpecSign(TSS S, SourceLocation Loc,
- const char *&PrevSpec,
- unsigned &DiagID) {
- if (TypeSpecSign != TSS_unspecified)
- return BadSpecifier(S, (TSS)TypeSpecSign, PrevSpec, DiagID);
- TypeSpecSign = S;
+bool DeclSpec::SetTypeSpecSign(TypeSpecifierSign S, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID) {
+ if (getTypeSpecSign() != TypeSpecifierSign::Unspecified)
+ return BadSpecifier(S, getTypeSpecSign(), PrevSpec, DiagID);
+ TypeSpecSign = static_cast<unsigned>(S);
TSSLoc = Loc;
return false;
}
@@ -870,7 +883,7 @@ bool DeclSpec::SetTypePipe(bool isPipe, SourceLocation Loc,
}
if (isPipe) {
- TypeSpecPipe = TSP_pipe;
+ TypeSpecPipe = static_cast<unsigned>(TypeSpecifiersPipe::Pipe);
}
return false;
}
@@ -1014,9 +1027,6 @@ bool DeclSpec::setFunctionSpecExplicit(SourceLocation Loc,
const char *&PrevSpec, unsigned &DiagID,
ExplicitSpecifier ExplicitSpec,
SourceLocation CloseParenLoc) {
- assert((ExplicitSpec.getKind() == ExplicitSpecKind::ResolvedTrue ||
- ExplicitSpec.getExpr()) &&
- "invalid ExplicitSpecifier");
// 'explicit explicit' is ok, but warn as this is likely not what the user
// intended.
if (hasExplicitSpecifier()) {
@@ -1080,17 +1090,17 @@ bool DeclSpec::setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec,
bool DeclSpec::SetConstexprSpec(ConstexprSpecKind ConstexprKind,
SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID) {
- if (getConstexprSpecifier() != CSK_unspecified)
+ if (getConstexprSpecifier() != ConstexprSpecKind::Unspecified)
return BadSpecifier(ConstexprKind, getConstexprSpecifier(), PrevSpec,
DiagID);
- ConstexprSpecifier = ConstexprKind;
+ ConstexprSpecifier = static_cast<unsigned>(ConstexprKind);
ConstexprLoc = Loc;
return false;
}
void DeclSpec::SaveWrittenBuiltinSpecs() {
- writtenBS.Sign = getTypeSpecSign();
- writtenBS.Width = getTypeSpecWidth();
+ writtenBS.Sign = static_cast<int>(getTypeSpecSign());
+ writtenBS.Width = static_cast<int>(getTypeSpecWidth());
writtenBS.Type = getTypeSpecType();
// Search the list of attributes for the presence of a mode attribute.
writtenBS.ModeAttr = getAttributes().hasAttribute(ParsedAttr::AT_Mode);
@@ -1111,9 +1121,9 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
// If decltype(auto) is used, no other type specifiers are permitted.
if (TypeSpecType == TST_decltype_auto &&
- (TypeSpecWidth != TSW_unspecified ||
+ (getTypeSpecWidth() != TypeSpecifierWidth::Unspecified ||
TypeSpecComplex != TSC_unspecified ||
- TypeSpecSign != TSS_unspecified ||
+ getTypeSpecSign() != TypeSpecifierSign::Unspecified ||
TypeAltiVecVector || TypeAltiVecPixel || TypeAltiVecBool ||
TypeQualifiers)) {
const unsigned NumLocs = 9;
@@ -1132,9 +1142,9 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
Hints[I] = FixItHint::CreateRemoval(ExtraLocs[I]);
}
}
- TypeSpecWidth = TSW_unspecified;
+ TypeSpecWidth = static_cast<unsigned>(TypeSpecifierWidth::Unspecified);
TypeSpecComplex = TSC_unspecified;
- TypeSpecSign = TSS_unspecified;
+ TypeSpecSign = static_cast<unsigned>(TypeSpecifierSign::Unspecified);
TypeAltiVecVector = TypeAltiVecPixel = TypeAltiVecBool = false;
TypeQualifiers = 0;
S.Diag(TSTLoc, diag::err_decltype_auto_cannot_be_combined)
@@ -1146,9 +1156,9 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
if (TypeAltiVecVector) {
if (TypeAltiVecBool) {
// Sign specifiers are not allowed with vector bool. (PIM 2.1)
- if (TypeSpecSign != TSS_unspecified) {
+ if (getTypeSpecSign() != TypeSpecifierSign::Unspecified) {
S.Diag(TSSLoc, diag::err_invalid_vector_bool_decl_spec)
- << getSpecifierName((TSS)TypeSpecSign);
+ << getSpecifierName(getTypeSpecSign());
}
// Only char/int are valid with vector bool prior to Power10.
// Power10 adds instructions that produce vector bool data
@@ -1166,13 +1176,14 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
S.Diag(TSTLoc, diag::err_invalid_vector_bool_int128_decl_spec);
// Only 'short' and 'long long' are valid with vector bool. (PIM 2.1)
- if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short) &&
- (TypeSpecWidth != TSW_longlong))
+ if ((getTypeSpecWidth() != TypeSpecifierWidth::Unspecified) &&
+ (getTypeSpecWidth() != TypeSpecifierWidth::Short) &&
+ (getTypeSpecWidth() != TypeSpecifierWidth::LongLong))
S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_bool_decl_spec)
- << getSpecifierName((TSW)TypeSpecWidth);
+ << getSpecifierName(getTypeSpecWidth());
// vector bool long long requires VSX support or ZVector.
- if ((TypeSpecWidth == TSW_longlong) &&
+ if ((getTypeSpecWidth() == TypeSpecifierWidth::LongLong) &&
(!S.Context.getTargetInfo().hasFeature("vsx")) &&
(!S.Context.getTargetInfo().hasFeature("power8-vector")) &&
!S.getLangOpts().ZVector)
@@ -1180,12 +1191,14 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
// Elements of vector bool are interpreted as unsigned. (PIM 2.1)
if ((TypeSpecType == TST_char) || (TypeSpecType == TST_int) ||
- (TypeSpecType == TST_int128) || (TypeSpecWidth != TSW_unspecified))
- TypeSpecSign = TSS_unsigned;
+ (TypeSpecType == TST_int128) ||
+ (getTypeSpecWidth() != TypeSpecifierWidth::Unspecified))
+ TypeSpecSign = static_cast<unsigned>(TypeSpecifierSign::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, and ZVector.
- if (TypeSpecWidth == TSW_long || TypeSpecWidth == TSW_longlong)
+ if (getTypeSpecWidth() == TypeSpecifierWidth::Long ||
+ getTypeSpecWidth() == TypeSpecifierWidth::LongLong)
S.Diag(TSWRange.getBegin(),
diag::err_invalid_vector_long_double_decl_spec);
else if (!S.Context.getTargetInfo().hasFeature("vsx") &&
@@ -1197,9 +1210,15 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
if (S.getLangOpts().ZVector &&
!S.Context.getTargetInfo().hasFeature("arch12"))
S.Diag(TSTLoc, diag::err_invalid_vector_float_decl_spec);
- } else if (TypeSpecWidth == TSW_long) {
+ } else if (getTypeSpecWidth() == TypeSpecifierWidth::Long) {
// vector long is unsupported for ZVector and deprecated for AltiVec.
- if (S.getLangOpts().ZVector)
+ // It has also been historically deprecated on AIX (as an alias for
+ // "vector int" in both 32-bit and 64-bit modes). It was then made
+ // unsupported in the Clang-based XL compiler since the deprecated type
+ // has a number of conflicting semantics and continuing to support it
+ // is a disservice to users.
+ if (S.getLangOpts().ZVector ||
+ S.Context.getTargetInfo().getTriple().isOSAIX())
S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_long_decl_spec);
else
S.Diag(TSWRange.getBegin(),
@@ -1210,8 +1229,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
if (TypeAltiVecPixel) {
//TODO: perform validation
TypeSpecType = TST_int;
- TypeSpecSign = TSS_unsigned;
- TypeSpecWidth = TSW_short;
+ TypeSpecSign = static_cast<unsigned>(TypeSpecifierSign::Unsigned);
+ TypeSpecWidth = static_cast<unsigned>(TypeSpecifierWidth::Short);
TypeSpecOwned = false;
}
}
@@ -1220,7 +1239,7 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
TypeSpecType == TST_accum || TypeSpecType == TST_fract;
// signed/unsigned are only valid with int/char/wchar_t/_Accum.
- if (TypeSpecSign != TSS_unspecified) {
+ if (getTypeSpecSign() != TypeSpecifierSign::Unspecified) {
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int.
else if (TypeSpecType != TST_int && TypeSpecType != TST_int128 &&
@@ -1229,19 +1248,21 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
S.Diag(TSSLoc, diag::err_invalid_sign_spec)
<< getSpecifierName((TST)TypeSpecType, Policy);
// signed double -> double.
- TypeSpecSign = TSS_unspecified;
+ TypeSpecSign = static_cast<unsigned>(TypeSpecifierSign::Unspecified);
}
}
// Validate the width of the type.
- switch (TypeSpecWidth) {
- case TSW_unspecified: break;
- case TSW_short: // short int
- case TSW_longlong: // long long int
+ switch (getTypeSpecWidth()) {
+ case TypeSpecifierWidth::Unspecified:
+ break;
+ case TypeSpecifierWidth::Short: // short int
+ case TypeSpecifierWidth::LongLong: // long long int
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // short -> short int, long long -> long long int.
else if (!(TypeSpecType == TST_int ||
- (IsFixedPointType && TypeSpecWidth != TSW_longlong))) {
+ (IsFixedPointType &&
+ getTypeSpecWidth() != TypeSpecifierWidth::LongLong))) {
S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec)
<< (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecType = TST_int;
@@ -1249,7 +1270,7 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
TypeSpecOwned = false;
}
break;
- case TSW_long: // long double, long int
+ case TypeSpecifierWidth::Long: // long double, long int
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // long -> long int.
else if (TypeSpecType != TST_int && TypeSpecType != TST_double &&
@@ -1279,6 +1300,7 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
S.Diag(TSTLoc, diag::ext_integer_complex);
} else if (TypeSpecType != TST_float && TypeSpecType != TST_double &&
TypeSpecType != TST_float128) {
+ // FIXME: _Float16, __fp16?
S.Diag(TSCLoc, diag::err_invalid_complex_spec)
<< getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecComplex = TSC_unspecified;
@@ -1337,11 +1359,11 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
else if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32)
S.Diag(TSTLoc, diag::warn_cxx98_compat_unicode_type)
<< (TypeSpecType == TST_char16 ? "char16_t" : "char32_t");
- if (getConstexprSpecifier() == CSK_constexpr)
+ if (getConstexprSpecifier() == ConstexprSpecKind::Constexpr)
S.Diag(ConstexprLoc, diag::warn_cxx98_compat_constexpr);
- else if (getConstexprSpecifier() == CSK_consteval)
+ else if (getConstexprSpecifier() == ConstexprSpecKind::Consteval)
S.Diag(ConstexprLoc, diag::warn_cxx20_compat_consteval);
- else if (getConstexprSpecifier() == CSK_constinit)
+ else if (getConstexprSpecifier() == ConstexprSpecKind::Constinit)
S.Diag(ConstexprLoc, diag::warn_cxx20_compat_constinit);
// C++ [class.friend]p6:
// No storage-class-specifier shall appear in the decl-specifier-seq
@@ -1422,9 +1444,10 @@ void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc,
Kind = UnqualifiedIdKind::IK_OperatorFunctionId;
StartLocation = OperatorLoc;
EndLocation = OperatorLoc;
+ new (&OperatorFunctionId) struct OFI;
OperatorFunctionId.Operator = Op;
for (unsigned I = 0; I != 3; ++I) {
- OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I].getRawEncoding();
+ OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I];
if (SymbolLocations[I].isValid())
EndLocation = SymbolLocations[I];
diff --git a/clang/lib/Sema/JumpDiagnostics.cpp b/clang/lib/Sema/JumpDiagnostics.cpp
index b34243edea35..d33b14a79dc1 100644
--- a/clang/lib/Sema/JumpDiagnostics.cpp
+++ b/clang/lib/Sema/JumpDiagnostics.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtOpenMP.h"
#include "llvm/ADT/BitVector.h"
using namespace clang;
@@ -580,6 +581,17 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S,
break;
default:
+ if (auto *ED = dyn_cast<OMPExecutableDirective>(S)) {
+ if (!ED->isStandaloneDirective()) {
+ unsigned NewParentScope = Scopes.size();
+ Scopes.emplace_back(ParentScope,
+ diag::note_omp_protected_structured_block,
+ diag::note_omp_exits_structured_block,
+ ED->getStructuredBlock()->getBeginLoc());
+ BuildScopeInformation(ED->getStructuredBlock(), NewParentScope);
+ return;
+ }
+ }
break;
}
@@ -904,6 +916,11 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
S.Diag(From->getBeginLoc(), diag::warn_jump_out_of_seh_finally);
break;
}
+ if (Scopes[I].InDiag == diag::note_omp_protected_structured_block) {
+ S.Diag(From->getBeginLoc(), diag::err_goto_into_protected_scope);
+ S.Diag(To->getBeginLoc(), diag::note_omp_exits_structured_block);
+ break;
+ }
}
}
diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp
index 80333e63127e..252008cda15d 100644
--- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -172,13 +172,6 @@ Module *MultiplexExternalSemaSource::getModule(unsigned ID) {
return nullptr;
}
-bool MultiplexExternalSemaSource::DeclIsFromPCHWithObjectFile(const Decl *D) {
- for (auto *S : Sources)
- if (S->DeclIsFromPCHWithObjectFile(D))
- return true;
- return false;
-}
-
bool MultiplexExternalSemaSource::layoutRecordType(const RecordDecl *Record,
uint64_t &Size,
uint64_t &Alignment,
diff --git a/clang/lib/Sema/ScopeInfo.cpp b/clang/lib/Sema/ScopeInfo.cpp
index b2a26af9b4a5..4857346018ae 100644
--- a/clang/lib/Sema/ScopeInfo.cpp
+++ b/clang/lib/Sema/ScopeInfo.cpp
@@ -29,6 +29,7 @@ void FunctionScopeInfo::Clear() {
HasDroppedStmt = false;
HasOMPDeclareReductionCombiner = false;
HasFallthroughStmt = false;
+ UsesFPIntrin = false;
HasPotentialAvailabilityViolations = false;
ObjCShouldCallSuper = false;
ObjCIsDesignatedInit = false;
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 2f2b52106f3d..55cb3aee6194 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -42,7 +42,7 @@
#include "clang/Sema/TemplateInstCallback.h"
#include "clang/Sema/TypoCorrection.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/TimeProfiler.h"
using namespace clang;
@@ -120,8 +120,9 @@ public:
}
IncludeStack.push_back(IncludeLoc);
- S->DiagnoseNonDefaultPragmaPack(
- Sema::PragmaPackDiagnoseKind::NonDefaultStateAtInclude, IncludeLoc);
+ S->DiagnoseNonDefaultPragmaAlignPack(
+ Sema::PragmaAlignPackDiagnoseKind::NonDefaultStateAtInclude,
+ IncludeLoc);
}
break;
}
@@ -130,8 +131,8 @@ public:
if (llvm::timeTraceProfilerEnabled())
llvm::timeTraceProfilerEnd();
- S->DiagnoseNonDefaultPragmaPack(
- Sema::PragmaPackDiagnoseKind::ChangedStateAtExit,
+ S->DiagnoseNonDefaultPragmaAlignPack(
+ Sema::PragmaAlignPackDiagnoseKind::ChangedStateAtExit,
IncludeStack.pop_back_val());
}
break;
@@ -157,10 +158,12 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
OriginalLexicalContext(nullptr), MSStructPragmaOn(false),
MSPointerToMemberRepresentationMethod(
LangOpts.getMSPointerToMemberRepresentationMethod()),
- VtorDispStack(LangOpts.getVtorDispMode()), PackStack(0),
+ VtorDispStack(LangOpts.getVtorDispMode()),
+ AlignPackStack(AlignPackInfo(getLangOpts().XLPragmaPack)),
DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr),
- CodeSegStack(nullptr), FpPragmaStack(0xffffffff), CurInitSeg(nullptr),
- VisContext(nullptr), PragmaAttributeCurrentTargetDecl(nullptr),
+ CodeSegStack(nullptr), FpPragmaStack(FPOptionsOverride()),
+ CurInitSeg(nullptr), VisContext(nullptr),
+ PragmaAttributeCurrentTargetDecl(nullptr),
IsBuildingRecoveryCallExpr(false), Cleanup{}, LateTemplateParser(nullptr),
LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp),
StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr),
@@ -235,7 +238,9 @@ void Sema::Initialize() {
return;
// Initialize predefined 128-bit integer types, if needed.
- if (Context.getTargetInfo().hasInt128Type()) {
+ if (Context.getTargetInfo().hasInt128Type() ||
+ (Context.getAuxTargetInfo() &&
+ Context.getAuxTargetInfo()->hasInt128Type())) {
// If either of the 128-bit integer types are unavailable to name lookup,
// define them now.
DeclarationName Int128 = &Context.Idents.get("__int128_t");
@@ -292,7 +297,7 @@ void Sema::Initialize() {
// core features.
if (getLangOpts().OpenCL) {
getOpenCLOptions().addSupport(
- Context.getTargetInfo().getSupportedOpenCLOpts());
+ Context.getTargetInfo().getSupportedOpenCLOpts(), getLangOpts());
getOpenCLOptions().enableSupportedCore(getLangOpts());
addImplicitTypedef("sampler_t", Context.OCLSamplerTy);
addImplicitTypedef("event_t", Context.OCLEventTy);
@@ -368,6 +373,18 @@ void Sema::Initialize() {
#include "clang/Basic/AArch64SVEACLETypes.def"
}
+ if (Context.getTargetInfo().getTriple().isPPC64() &&
+ Context.getTargetInfo().hasFeature("paired-vector-memops")) {
+ if (Context.getTargetInfo().hasFeature("mma")) {
+#define PPC_VECTOR_MMA_TYPE(Name, Id, Size) \
+ addImplicitTypedef(#Name, Context.Id##Ty);
+#include "clang/Basic/PPCTypes.def"
+ }
+#define PPC_VECTOR_VSX_TYPE(Name, Id, Size) \
+ addImplicitTypedef(#Name, Context.Id##Ty);
+#include "clang/Basic/PPCTypes.def"
+ }
+
if (Context.getTargetInfo().hasBuiltinMSVaList()) {
DeclarationName MSVaList = &Context.Idents.get("__builtin_ms_va_list");
if (IdResolver.begin(MSVaList) == IdResolver.end())
@@ -380,6 +397,9 @@ void Sema::Initialize() {
}
Sema::~Sema() {
+ assert(InstantiatingSpecializations.empty() &&
+ "failed to clean up an InstantiatingTemplate?");
+
if (VisContext) FreeVisContext();
// Kill all the active scopes.
@@ -493,7 +513,8 @@ void Sema::diagnoseNullableToNonnullConversion(QualType DstType,
QualType SrcType,
SourceLocation Loc) {
Optional<NullabilityKind> ExprNullability = SrcType->getNullability(Context);
- if (!ExprNullability || *ExprNullability != NullabilityKind::Nullable)
+ if (!ExprNullability || (*ExprNullability != NullabilityKind::Nullable &&
+ *ExprNullability != NullabilityKind::NullableResult))
return;
Optional<NullabilityKind> TypeNullability = DstType->getNullability(Context);
@@ -539,8 +560,10 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
if (VK == VK_RValue && !E->isRValue()) {
switch (Kind) {
default:
- llvm_unreachable("can't implicitly cast lvalue to rvalue with this cast "
- "kind");
+ llvm_unreachable(("can't implicitly cast lvalue to rvalue with this cast "
+ "kind: " +
+ std::string(CastExpr::getCastKindName(Kind)))
+ .c_str());
case CK_Dependent:
case CK_LValueToRValue:
case CK_ArrayToPointerDecay:
@@ -583,7 +606,8 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
}
}
- return ImplicitCastExpr::Create(Context, Ty, Kind, E, BasePath, VK);
+ return ImplicitCastExpr::Create(Context, Ty, Kind, E, BasePath, VK,
+ CurFPFeatureOverrides());
}
/// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding
@@ -1016,7 +1040,7 @@ void Sema::ActOnEndOfTranslationUnit() {
}
}
- DiagnoseUnterminatedPragmaPack();
+ DiagnoseUnterminatedPragmaAlignPack();
DiagnoseUnterminatedPragmaAttribute();
// All delayed member exception specs should be checked or we end up accepting
@@ -1195,7 +1219,7 @@ void Sema::ActOnEndOfTranslationUnit() {
if (DiagD->isReferenced()) {
if (isa<CXXMethodDecl>(DiagD))
Diag(DiagD->getLocation(), diag::warn_unneeded_member_function)
- << DiagD->getDeclName();
+ << DiagD;
else {
if (FD->getStorageClass() == SC_Static &&
!FD->isInlineSpecified() &&
@@ -1203,20 +1227,20 @@ void Sema::ActOnEndOfTranslationUnit() {
SourceMgr.getExpansionLoc(FD->getLocation())))
Diag(DiagD->getLocation(),
diag::warn_unneeded_static_internal_decl)
- << DiagD->getDeclName();
+ << DiagD;
else
Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
- << /*function*/0 << DiagD->getDeclName();
+ << /*function*/ 0 << DiagD;
}
} else {
if (FD->getDescribedFunctionTemplate())
Diag(DiagD->getLocation(), diag::warn_unused_template)
- << /*function*/0 << DiagD->getDeclName();
+ << /*function*/ 0 << DiagD;
else
- Diag(DiagD->getLocation(),
- isa<CXXMethodDecl>(DiagD) ? diag::warn_unused_member_function
+ Diag(DiagD->getLocation(), isa<CXXMethodDecl>(DiagD)
+ ? diag::warn_unused_member_function
: diag::warn_unused_function)
- << DiagD->getDeclName();
+ << DiagD;
}
} else {
const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition();
@@ -1224,20 +1248,19 @@ void Sema::ActOnEndOfTranslationUnit() {
DiagD = cast<VarDecl>(*I);
if (DiagD->isReferenced()) {
Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
- << /*variable*/1 << DiagD->getDeclName();
+ << /*variable*/ 1 << DiagD;
} else if (DiagD->getType().isConstQualified()) {
const SourceManager &SM = SourceMgr;
if (SM.getMainFileID() != SM.getFileID(DiagD->getLocation()) ||
!PP.getLangOpts().IsHeaderFile)
Diag(DiagD->getLocation(), diag::warn_unused_const_variable)
- << DiagD->getDeclName();
+ << DiagD;
} else {
if (DiagD->getDescribedVarTemplate())
Diag(DiagD->getLocation(), diag::warn_unused_template)
- << /*variable*/1 << DiagD->getDeclName();
+ << /*variable*/ 1 << DiagD;
else
- Diag(DiagD->getLocation(), diag::warn_unused_variable)
- << DiagD->getDeclName();
+ Diag(DiagD->getLocation(), diag::warn_unused_variable) << DiagD;
}
}
}
@@ -1433,11 +1456,24 @@ void Sema::EmitCurrentDiagnostic(unsigned DiagID) {
}
Sema::SemaDiagnosticBuilder
-Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) {
- SemaDiagnosticBuilder Builder(Diag(Loc, PD.getDiagID()));
- PD.Emit(Builder);
+Sema::Diag(SourceLocation Loc, const PartialDiagnostic &PD, bool DeferHint) {
+ return Diag(Loc, PD.getDiagID(), DeferHint) << PD;
+}
- return Builder;
+bool Sema::hasUncompilableErrorOccurred() const {
+ if (getDiagnostics().hasUncompilableErrorOccurred())
+ return true;
+ auto *FD = dyn_cast<FunctionDecl>(CurContext);
+ if (!FD)
+ return false;
+ auto Loc = DeviceDeferredDiags.find(FD);
+ if (Loc == DeviceDeferredDiags.end())
+ return false;
+ for (auto PDAt : Loc->second) {
+ if (DiagnosticIDs::isDefaultMappingAsError(PDAt.second.getDiagID()))
+ return true;
+ }
+ return false;
}
// Print notes showing how we can reach FD starting from an a priori
@@ -1490,7 +1526,7 @@ public:
typedef UsedDeclVisitor<DeferredDiagnosticsEmitter> Inherited;
// Whether the function is already in the current use-path.
- llvm::SmallSet<CanonicalDeclPtr<Decl>, 4> InUsePath;
+ llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> InUsePath;
// The current use-path.
llvm::SmallVector<CanonicalDeclPtr<FunctionDecl>, 4> UsePath;
@@ -1499,7 +1535,7 @@ public:
// case not in OpenMP device context. Done[1] is for the case in OpenMP
// device context. We need two sets because diagnostics emission may be
// different depending on whether it is in OpenMP device context.
- llvm::SmallSet<CanonicalDeclPtr<Decl>, 4> DoneMap[2];
+ llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> DoneMap[2];
// Emission state of the root node of the current use graph.
bool ShouldEmitRootNode;
@@ -1549,7 +1585,8 @@ public:
S.shouldIgnoreInHostDeviceCheck(FD) || InUsePath.count(FD))
return;
// Finalize analysis of OpenMP-specific constructs.
- if (Caller && S.LangOpts.OpenMP && UsePath.size() == 1)
+ if (Caller && S.LangOpts.OpenMP && UsePath.size() == 1 &&
+ (ShouldEmitRootNode || InOMPDeviceContext))
S.finalizeOpenMPDelayedAnalysis(Caller, FD, Loc);
if (Caller)
S.DeviceKnownEmittedFns[FD] = {Caller, Loc};
@@ -1649,9 +1686,9 @@ void Sema::emitDeferredDiags() {
// until we discover that the function is known-emitted, at which point we take
// it out of this map and emit the diagnostic.
-Sema::DeviceDiagBuilder::DeviceDiagBuilder(Kind K, SourceLocation Loc,
- unsigned DiagID, FunctionDecl *Fn,
- Sema &S)
+Sema::SemaDiagnosticBuilder::SemaDiagnosticBuilder(Kind K, SourceLocation Loc,
+ unsigned DiagID,
+ FunctionDecl *Fn, Sema &S)
: S(S), Loc(Loc), DiagID(DiagID), Fn(Fn),
ShowCallStack(K == K_ImmediateWithCallStack || K == K_Deferred) {
switch (K) {
@@ -1659,7 +1696,8 @@ Sema::DeviceDiagBuilder::DeviceDiagBuilder(Kind K, SourceLocation Loc,
break;
case K_Immediate:
case K_ImmediateWithCallStack:
- ImmediateDiag.emplace(S.Diag(Loc, DiagID));
+ ImmediateDiag.emplace(
+ ImmediateDiagBuilder(S.Diags.Report(Loc, DiagID), S, DiagID));
break;
case K_Deferred:
assert(Fn && "Must have a function to attach the deferred diag to.");
@@ -1670,7 +1708,7 @@ Sema::DeviceDiagBuilder::DeviceDiagBuilder(Kind K, SourceLocation Loc,
}
}
-Sema::DeviceDiagBuilder::DeviceDiagBuilder(DeviceDiagBuilder &&D)
+Sema::SemaDiagnosticBuilder::SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D)
: S(D.S), Loc(D.Loc), DiagID(D.DiagID), Fn(D.Fn),
ShowCallStack(D.ShowCallStack), ImmediateDiag(D.ImmediateDiag),
PartialDiagId(D.PartialDiagId) {
@@ -1680,7 +1718,7 @@ Sema::DeviceDiagBuilder::DeviceDiagBuilder(DeviceDiagBuilder &&D)
D.PartialDiagId.reset();
}
-Sema::DeviceDiagBuilder::~DeviceDiagBuilder() {
+Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
if (ImmediateDiag) {
// Emit our diagnostic and, if it was a warning or error, output a callstack
// if Fn isn't a priori known-emitted.
@@ -1695,7 +1733,8 @@ Sema::DeviceDiagBuilder::~DeviceDiagBuilder() {
}
}
-Sema::DeviceDiagBuilder Sema::targetDiag(SourceLocation Loc, unsigned DiagID) {
+Sema::SemaDiagnosticBuilder Sema::targetDiag(SourceLocation Loc,
+ unsigned DiagID) {
if (LangOpts.OpenMP)
return LangOpts.OpenMPIsDevice ? diagIfOpenMPDeviceCode(Loc, DiagID)
: diagIfOpenMPHostCode(Loc, DiagID);
@@ -1706,8 +1745,32 @@ Sema::DeviceDiagBuilder Sema::targetDiag(SourceLocation Loc, unsigned DiagID) {
if (getLangOpts().SYCLIsDevice)
return SYCLDiagIfDeviceCode(Loc, DiagID);
- return DeviceDiagBuilder(DeviceDiagBuilder::K_Immediate, Loc, DiagID,
- getCurFunctionDecl(), *this);
+ return SemaDiagnosticBuilder(SemaDiagnosticBuilder::K_Immediate, Loc, DiagID,
+ getCurFunctionDecl(), *this);
+}
+
+Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID,
+ bool DeferHint) {
+ bool IsError = Diags.getDiagnosticIDs()->isDefaultMappingAsError(DiagID);
+ bool ShouldDefer = getLangOpts().CUDA && LangOpts.GPUDeferDiag &&
+ DiagnosticIDs::isDeferrable(DiagID) &&
+ (DeferHint || !IsError);
+ auto SetIsLastErrorImmediate = [&](bool Flag) {
+ if (IsError)
+ IsLastErrorImmediate = Flag;
+ };
+ if (!ShouldDefer) {
+ SetIsLastErrorImmediate(true);
+ return SemaDiagnosticBuilder(SemaDiagnosticBuilder::K_Immediate, Loc,
+ DiagID, getCurFunctionDecl(), *this);
+ }
+
+ SemaDiagnosticBuilder DB =
+ getLangOpts().CUDAIsDevice
+ ? CUDADiagIfDeviceCode(Loc, DiagID)
+ : CUDADiagIfHostCode(Loc, DiagID);
+ SetIsLastErrorImmediate(DB.isImmediate());
+ return DB;
}
void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) {
@@ -1732,6 +1795,15 @@ void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) {
if (Ty->isDependentType())
return;
+ if (Ty->isExtIntType()) {
+ if (!Context.getTargetInfo().hasExtIntType()) {
+ targetDiag(Loc, diag::err_device_unsupported_type)
+ << D << false /*show bit size*/ << 0 /*bitsize*/
+ << Ty << Context.getTargetInfo().getTriple().str();
+ }
+ return;
+ }
+
if ((Ty->isFloat16Type() && !Context.getTargetInfo().hasFloat16Type()) ||
((Ty->isFloat128Type() ||
(Ty->isRealFloatingType() && Context.getTypeSize(Ty) == 128)) &&
@@ -1739,7 +1811,8 @@ void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) {
(Ty->isIntegerType() && Context.getTypeSize(Ty) == 128 &&
!Context.getTargetInfo().hasInt128Type())) {
targetDiag(Loc, diag::err_device_unsupported_type)
- << D << static_cast<unsigned>(Context.getTypeSize(Ty)) << Ty
+ << D << true /*show bit size*/
+ << static_cast<unsigned>(Context.getTypeSize(Ty)) << Ty
<< Context.getTargetInfo().getTriple().str();
targetDiag(D->getLocation(), diag::note_defined_here) << D;
}
@@ -1768,7 +1841,7 @@ bool Sema::findMacroSpelling(SourceLocation &locref, StringRef name) {
loc = getSourceManager().getExpansionLoc(loc);
// If that's written with the name, stop here.
- SmallVector<char, 16> buffer;
+ SmallString<16> buffer;
if (getPreprocessor().getSpelling(loc, buffer) == name) {
locref = loc;
return true;
diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp
index bd15b81cbed0..be30445d143c 100644
--- a/clang/lib/Sema/SemaAccess.cpp
+++ b/clang/lib/Sema/SemaAccess.cpp
@@ -1476,7 +1476,8 @@ void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *D) {
} else if (FunctionDecl *FN = dyn_cast<FunctionDecl>(D)) {
DC = FN;
} else if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) {
- DC = cast<DeclContext>(TD->getTemplatedDecl());
+ if (isa<DeclContext>(TD->getTemplatedDecl()))
+ DC = cast<DeclContext>(TD->getTemplatedDecl());
}
EffectiveContext EC(DC);
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index b354e810974c..6e441a0ded0d 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -48,28 +48,38 @@ Sema::PragmaStackSentinelRAII::~PragmaStackSentinelRAII() {
}
void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
- // If there is no pack value, we don't need any attributes.
- if (!PackStack.CurrentValue)
+ AlignPackInfo InfoVal = AlignPackStack.CurrentValue;
+ AlignPackInfo::Mode M = InfoVal.getAlignMode();
+ bool IsPackSet = InfoVal.IsPackSet();
+ bool IsXLPragma = getLangOpts().XLPragmaPack;
+
+ // If we are not under mac68k/natural alignment mode and also there is no pack
+ // value, we don't need any attributes.
+ if (!IsPackSet && M != AlignPackInfo::Mac68k && M != AlignPackInfo::Natural)
return;
- // Otherwise, check to see if we need a max field alignment attribute.
- if (unsigned Alignment = PackStack.CurrentValue) {
- if (Alignment == Sema::kMac68kAlignmentSentinel)
- RD->addAttr(AlignMac68kAttr::CreateImplicit(Context));
- else
- RD->addAttr(MaxFieldAlignmentAttr::CreateImplicit(Context,
- Alignment * 8));
+ if (M == AlignPackInfo::Mac68k && (IsXLPragma || InfoVal.IsAlignAttr())) {
+ RD->addAttr(AlignMac68kAttr::CreateImplicit(Context));
+ } else if (IsPackSet) {
+ // Check to see if we need a max field alignment attribute.
+ RD->addAttr(MaxFieldAlignmentAttr::CreateImplicit(
+ Context, InfoVal.getPackNumber() * 8));
}
- if (PackIncludeStack.empty())
+
+ if (IsXLPragma && M == AlignPackInfo::Natural)
+ RD->addAttr(AlignNaturalAttr::CreateImplicit(Context));
+
+ if (AlignPackIncludeStack.empty())
return;
- // The #pragma pack affected a record in an included file, so Clang should
- // warn when that pragma was written in a file that included the included
- // file.
- for (auto &PackedInclude : llvm::reverse(PackIncludeStack)) {
- if (PackedInclude.CurrentPragmaLocation != PackStack.CurrentPragmaLocation)
+ // The #pragma align/pack affected a record in an included file, so Clang
+ // should warn when that pragma was written in a file that included the
+ // included file.
+ for (auto &AlignPackedInclude : llvm::reverse(AlignPackIncludeStack)) {
+ if (AlignPackedInclude.CurrentPragmaLocation !=
+ AlignPackStack.CurrentPragmaLocation)
break;
- if (PackedInclude.HasNonDefaultValue)
- PackedInclude.ShouldWarnOnInclude = true;
+ if (AlignPackedInclude.HasNonDefaultValue)
+ AlignPackedInclude.ShouldWarnOnInclude = true;
}
}
@@ -205,23 +215,27 @@ void Sema::inferGslOwnerPointerAttribute(CXXRecordDecl *Record) {
void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
SourceLocation PragmaLoc) {
PragmaMsStackAction Action = Sema::PSK_Reset;
- unsigned Alignment = 0;
+ AlignPackInfo::Mode ModeVal = AlignPackInfo::Native;
+
switch (Kind) {
- // For all targets we support native and natural are the same.
+ // For most of the platforms we support, native and natural are the same.
+ // With XL, native is the same as power, natural means something else.
//
// FIXME: This is not true on Darwin/PPC.
case POAK_Native:
case POAK_Power:
+ Action = Sema::PSK_Push_Set;
+ break;
case POAK_Natural:
Action = Sema::PSK_Push_Set;
- Alignment = 0;
+ ModeVal = AlignPackInfo::Natural;
break;
// Note that '#pragma options align=packed' is not equivalent to attribute
// packed, it has a different precedence relative to attribute aligned.
case POAK_Packed:
Action = Sema::PSK_Push_Set;
- Alignment = 1;
+ ModeVal = AlignPackInfo::Packed;
break;
case POAK_Mac68k:
@@ -231,15 +245,15 @@ void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
return;
}
Action = Sema::PSK_Push_Set;
- Alignment = Sema::kMac68kAlignmentSentinel;
+ ModeVal = AlignPackInfo::Mac68k;
break;
-
case POAK_Reset:
// Reset just pops the top of the stack, or resets the current alignment to
// default.
Action = Sema::PSK_Pop;
- if (PackStack.Stack.empty()) {
- if (PackStack.CurrentValue) {
+ if (AlignPackStack.Stack.empty()) {
+ if (AlignPackStack.CurrentValue.getAlignMode() != AlignPackInfo::Native ||
+ AlignPackStack.CurrentValue.IsPackAttr()) {
Action = Sema::PSK_Reset;
} else {
Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
@@ -250,7 +264,9 @@ void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
break;
}
- PackStack.Act(PragmaLoc, Action, StringRef(), Alignment);
+ AlignPackInfo Info(ModeVal, getLangOpts().XLPragmaPack);
+
+ AlignPackStack.Act(PragmaLoc, Action, StringRef(), Info);
}
void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, PragmaClangSectionAction Action,
@@ -295,98 +311,129 @@ void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, PragmaClangSectionA
void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
StringRef SlotLabel, Expr *alignment) {
+ bool IsXLPragma = getLangOpts().XLPragmaPack;
+ // XL pragma pack does not support identifier syntax.
+ if (IsXLPragma && !SlotLabel.empty()) {
+ Diag(PragmaLoc, diag::err_pragma_pack_identifer_not_supported);
+ return;
+ }
+
+ const AlignPackInfo CurVal = AlignPackStack.CurrentValue;
Expr *Alignment = static_cast<Expr *>(alignment);
// If specified then alignment must be a "small" power of two.
unsigned AlignmentVal = 0;
+ AlignPackInfo::Mode ModeVal = CurVal.getAlignMode();
+
if (Alignment) {
- llvm::APSInt Val;
+ Optional<llvm::APSInt> Val;
+ Val = Alignment->getIntegerConstantExpr(Context);
// pack(0) is like pack(), which just works out since that is what
// we use 0 for in PackAttr.
- if (Alignment->isTypeDependent() ||
- Alignment->isValueDependent() ||
- !Alignment->isIntegerConstantExpr(Val, Context) ||
- !(Val == 0 || Val.isPowerOf2()) ||
- Val.getZExtValue() > 16) {
+ if (Alignment->isTypeDependent() || Alignment->isValueDependent() || !Val ||
+ !(*Val == 0 || Val->isPowerOf2()) || Val->getZExtValue() > 16) {
Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
return; // Ignore
}
- AlignmentVal = (unsigned) Val.getZExtValue();
+ if (IsXLPragma && *Val == 0) {
+ // pack(0) does not work out with XL.
+ Diag(PragmaLoc, diag::err_pragma_pack_invalid_alignment);
+ return; // Ignore
+ }
+
+ AlignmentVal = (unsigned)Val->getZExtValue();
}
+
if (Action == Sema::PSK_Show) {
// Show the current alignment, making sure to show the right value
// for the default.
// FIXME: This should come from the target.
- AlignmentVal = PackStack.CurrentValue;
- if (AlignmentVal == 0)
- AlignmentVal = 8;
- if (AlignmentVal == Sema::kMac68kAlignmentSentinel)
+ AlignmentVal = CurVal.IsPackSet() ? CurVal.getPackNumber() : 8;
+ if (ModeVal == AlignPackInfo::Mac68k &&
+ (IsXLPragma || CurVal.IsAlignAttr()))
Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k";
else
Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
}
+
// MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
// "#pragma pack(pop, identifier, n) is undefined"
if (Action & Sema::PSK_Pop) {
if (Alignment && !SlotLabel.empty())
Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifier_and_alignment);
- if (PackStack.Stack.empty())
+ if (AlignPackStack.Stack.empty()) {
+ assert(CurVal.getAlignMode() == AlignPackInfo::Native &&
+ "Empty pack stack can only be at Native alignment mode.");
Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "pack" << "stack empty";
+ }
}
- PackStack.Act(PragmaLoc, Action, SlotLabel, AlignmentVal);
+ AlignPackInfo Info(ModeVal, AlignmentVal, IsXLPragma);
+
+ AlignPackStack.Act(PragmaLoc, Action, SlotLabel, Info);
}
-void Sema::DiagnoseNonDefaultPragmaPack(PragmaPackDiagnoseKind Kind,
- SourceLocation IncludeLoc) {
- if (Kind == PragmaPackDiagnoseKind::NonDefaultStateAtInclude) {
- SourceLocation PrevLocation = PackStack.CurrentPragmaLocation;
+void Sema::DiagnoseNonDefaultPragmaAlignPack(PragmaAlignPackDiagnoseKind Kind,
+ SourceLocation IncludeLoc) {
+ if (Kind == PragmaAlignPackDiagnoseKind::NonDefaultStateAtInclude) {
+ SourceLocation PrevLocation = AlignPackStack.CurrentPragmaLocation;
// Warn about non-default alignment at #includes (without redundant
// warnings for the same directive in nested includes).
// The warning is delayed until the end of the file to avoid warnings
// for files that don't have any records that are affected by the modified
// alignment.
bool HasNonDefaultValue =
- PackStack.hasValue() &&
- (PackIncludeStack.empty() ||
- PackIncludeStack.back().CurrentPragmaLocation != PrevLocation);
- PackIncludeStack.push_back(
- {PackStack.CurrentValue,
- PackStack.hasValue() ? PrevLocation : SourceLocation(),
+ AlignPackStack.hasValue() &&
+ (AlignPackIncludeStack.empty() ||
+ AlignPackIncludeStack.back().CurrentPragmaLocation != PrevLocation);
+ AlignPackIncludeStack.push_back(
+ {AlignPackStack.CurrentValue,
+ AlignPackStack.hasValue() ? PrevLocation : SourceLocation(),
HasNonDefaultValue, /*ShouldWarnOnInclude*/ false});
return;
}
- assert(Kind == PragmaPackDiagnoseKind::ChangedStateAtExit && "invalid kind");
- PackIncludeState PrevPackState = PackIncludeStack.pop_back_val();
- if (PrevPackState.ShouldWarnOnInclude) {
+ assert(Kind == PragmaAlignPackDiagnoseKind::ChangedStateAtExit &&
+ "invalid kind");
+ AlignPackIncludeState PrevAlignPackState =
+ AlignPackIncludeStack.pop_back_val();
+ // FIXME: AlignPackStack may contain both #pragma align and #pragma pack
+ // information, diagnostics below might not be accurate if we have mixed
+ // pragmas.
+ if (PrevAlignPackState.ShouldWarnOnInclude) {
// Emit the delayed non-default alignment at #include warning.
Diag(IncludeLoc, diag::warn_pragma_pack_non_default_at_include);
- Diag(PrevPackState.CurrentPragmaLocation, diag::note_pragma_pack_here);
+ Diag(PrevAlignPackState.CurrentPragmaLocation, diag::note_pragma_pack_here);
}
// Warn about modified alignment after #includes.
- if (PrevPackState.CurrentValue != PackStack.CurrentValue) {
+ if (PrevAlignPackState.CurrentValue != AlignPackStack.CurrentValue) {
Diag(IncludeLoc, diag::warn_pragma_pack_modified_after_include);
- Diag(PackStack.CurrentPragmaLocation, diag::note_pragma_pack_here);
+ Diag(AlignPackStack.CurrentPragmaLocation, diag::note_pragma_pack_here);
}
}
-void Sema::DiagnoseUnterminatedPragmaPack() {
- if (PackStack.Stack.empty())
+void Sema::DiagnoseUnterminatedPragmaAlignPack() {
+ if (AlignPackStack.Stack.empty())
return;
bool IsInnermost = true;
- for (const auto &StackSlot : llvm::reverse(PackStack.Stack)) {
+
+ // FIXME: AlignPackStack may contain both #pragma align and #pragma pack
+ // information, diagnostics below might not be accurate if we have mixed
+ // pragmas.
+ for (const auto &StackSlot : llvm::reverse(AlignPackStack.Stack)) {
Diag(StackSlot.PragmaPushLocation, diag::warn_pragma_pack_no_pop_eof);
// The user might have already reset the alignment, so suggest replacing
// the reset with a pop.
- if (IsInnermost && PackStack.CurrentValue == PackStack.DefaultValue) {
- DiagnosticBuilder DB = Diag(PackStack.CurrentPragmaLocation,
- diag::note_pragma_pack_pop_instead_reset);
- SourceLocation FixItLoc = Lexer::findLocationAfterToken(
- PackStack.CurrentPragmaLocation, tok::l_paren, SourceMgr, LangOpts,
- /*SkipTrailing=*/false);
+ if (IsInnermost &&
+ AlignPackStack.CurrentValue == AlignPackStack.DefaultValue) {
+ auto DB = Diag(AlignPackStack.CurrentPragmaLocation,
+ diag::note_pragma_pack_pop_instead_reset);
+ SourceLocation FixItLoc =
+ Lexer::findLocationAfterToken(AlignPackStack.CurrentPragmaLocation,
+ tok::l_paren, SourceMgr, LangOpts,
+ /*SkipTrailing=*/false);
if (FixItLoc.isValid())
DB << FixItHint::CreateInsertion(FixItLoc, "pop");
}
@@ -417,10 +464,7 @@ void Sema::ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name,
void Sema::ActOnPragmaFloatControl(SourceLocation Loc,
PragmaMsStackAction Action,
PragmaFloatControlKind Value) {
- unsigned NewValue = FpPragmaStack.hasValue()
- ? FpPragmaStack.CurrentValue
- : CurFPFeatureOverrides().getAsOpaqueInt();
- FPOptionsOverride NewFPFeatures(NewValue);
+ FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
if ((Action == PSK_Push_Set || Action == PSK_Push || Action == PSK_Pop) &&
!(CurContext->isTranslationUnit()) && !CurContext->isNamespace()) {
// Push and pop can only occur at file or namespace scope.
@@ -432,8 +476,7 @@ void Sema::ActOnPragmaFloatControl(SourceLocation Loc,
llvm_unreachable("invalid pragma float_control kind");
case PFC_Precise:
NewFPFeatures.setFPPreciseEnabled(true);
- NewValue = NewFPFeatures.getAsOpaqueInt();
- FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
+ FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures);
break;
case PFC_NoPrecise:
if (CurFPFeatures.getFPExceptionMode() == LangOptions::FPE_Strict)
@@ -442,25 +485,21 @@ void Sema::ActOnPragmaFloatControl(SourceLocation Loc,
Diag(Loc, diag::err_pragma_fc_noprecise_requires_nofenv);
else
NewFPFeatures.setFPPreciseEnabled(false);
- NewValue = NewFPFeatures.getAsOpaqueInt();
- FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
+ FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures);
break;
case PFC_Except:
if (!isPreciseFPEnabled())
Diag(Loc, diag::err_pragma_fc_except_requires_precise);
else
NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Strict);
- NewValue = NewFPFeatures.getAsOpaqueInt();
- FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
+ FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures);
break;
case PFC_NoExcept:
NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Ignore);
- NewValue = NewFPFeatures.getAsOpaqueInt();
- FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
+ FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures);
break;
case PFC_Push:
- FpPragmaStack.Act(Loc, Sema::PSK_Push_Set, StringRef(),
- NewFPFeatures.getAsOpaqueInt());
+ FpPragmaStack.Act(Loc, Sema::PSK_Push_Set, StringRef(), NewFPFeatures);
break;
case PFC_Pop:
if (FpPragmaStack.Stack.empty()) {
@@ -468,14 +507,11 @@ void Sema::ActOnPragmaFloatControl(SourceLocation Loc,
<< "stack empty";
return;
}
- FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures.getAsOpaqueInt());
- NewValue = FpPragmaStack.CurrentValue;
+ FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures);
+ NewFPFeatures = FpPragmaStack.CurrentValue;
break;
}
- FPOptionsOverride NewOverrides;
- if (NewValue != FpPragmaStack.DefaultValue)
- NewOverrides.getFromOpaqueInt(NewValue);
- CurFPFeatures = NewOverrides.applyOverrides(getLangOpts());
+ CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
}
void Sema::ActOnPragmaMSPointersToMembers(
@@ -494,9 +530,70 @@ void Sema::ActOnPragmaMSVtorDisp(PragmaMsStackAction Action,
VtorDispStack.Act(PragmaLoc, Action, StringRef(), Mode);
}
-bool Sema::UnifySection(StringRef SectionName,
- int SectionFlags,
- DeclaratorDecl *Decl) {
+template <>
+void Sema::PragmaStack<Sema::AlignPackInfo>::Act(SourceLocation PragmaLocation,
+ PragmaMsStackAction Action,
+ llvm::StringRef StackSlotLabel,
+ AlignPackInfo Value) {
+ if (Action == PSK_Reset) {
+ CurrentValue = DefaultValue;
+ CurrentPragmaLocation = PragmaLocation;
+ return;
+ }
+ if (Action & PSK_Push)
+ Stack.emplace_back(Slot(StackSlotLabel, CurrentValue, CurrentPragmaLocation,
+ PragmaLocation));
+ else if (Action & PSK_Pop) {
+ if (!StackSlotLabel.empty()) {
+ // If we've got a label, try to find it and jump there.
+ auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) {
+ return x.StackSlotLabel == StackSlotLabel;
+ });
+ // We found the label, so pop from there.
+ if (I != Stack.rend()) {
+ CurrentValue = I->Value;
+ CurrentPragmaLocation = I->PragmaLocation;
+ Stack.erase(std::prev(I.base()), Stack.end());
+ }
+ } else if (Value.IsXLStack() && Value.IsAlignAttr() &&
+ CurrentValue.IsPackAttr()) {
+ // XL '#pragma align(reset)' would pop the stack until
+ // a current in effect pragma align is popped.
+ auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) {
+ return x.Value.IsAlignAttr();
+ });
+ // If we found pragma align so pop from there.
+ if (I != Stack.rend()) {
+ Stack.erase(std::prev(I.base()), Stack.end());
+ if (Stack.empty()) {
+ CurrentValue = DefaultValue;
+ CurrentPragmaLocation = PragmaLocation;
+ } else {
+ CurrentValue = Stack.back().Value;
+ CurrentPragmaLocation = Stack.back().PragmaLocation;
+ Stack.pop_back();
+ }
+ }
+ } else if (!Stack.empty()) {
+ // xl '#pragma align' sets the baseline, and `#pragma pack` cannot pop
+ // over the baseline.
+ if (Value.IsXLStack() && Value.IsPackAttr() && CurrentValue.IsAlignAttr())
+ return;
+
+ // We don't have a label, just pop the last entry.
+ CurrentValue = Stack.back().Value;
+ CurrentPragmaLocation = Stack.back().PragmaLocation;
+ Stack.pop_back();
+ }
+ }
+ if (Action & PSK_Set) {
+ CurrentValue = Value;
+ CurrentPragmaLocation = PragmaLocation;
+ }
+}
+
+bool Sema::UnifySection(StringRef SectionName, int SectionFlags,
+ NamedDecl *Decl) {
SourceLocation PragmaLocation;
if (auto A = Decl->getAttr<SectionAttr>())
if (A->isImplicit())
@@ -968,10 +1065,7 @@ void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType,
void Sema::ActOnPragmaFPContract(SourceLocation Loc,
LangOptions::FPModeKind FPC) {
- unsigned NewValue = FpPragmaStack.hasValue()
- ? FpPragmaStack.CurrentValue
- : CurFPFeatureOverrides().getAsOpaqueInt();
- FPOptionsOverride NewFPFeatures(NewValue);
+ FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
switch (FPC) {
case LangOptions::FPM_On:
NewFPFeatures.setAllowFPContractWithinStatement();
@@ -982,54 +1076,45 @@ void Sema::ActOnPragmaFPContract(SourceLocation Loc,
case LangOptions::FPM_Off:
NewFPFeatures.setDisallowFPContract();
break;
+ case LangOptions::FPM_FastHonorPragmas:
+ llvm_unreachable("Should not happen");
}
+ FpPragmaStack.Act(Loc, Sema::PSK_Set, StringRef(), NewFPFeatures);
CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
- FpPragmaStack.Act(Loc, Sema::PSK_Set, StringRef(),
- NewFPFeatures.getAsOpaqueInt());
}
void Sema::ActOnPragmaFPReassociate(SourceLocation Loc, bool IsEnabled) {
- unsigned NewValue = FpPragmaStack.hasValue()
- ? FpPragmaStack.CurrentValue
- : CurFPFeatureOverrides().getAsOpaqueInt();
- FPOptionsOverride NewFPFeatures(NewValue);
+ FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
NewFPFeatures.setAllowFPReassociateOverride(IsEnabled);
- NewValue = NewFPFeatures.getAsOpaqueInt();
- FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue);
- FPOptionsOverride NewOverrides(NewValue);
- CurFPFeatures = NewOverrides.applyOverrides(getLangOpts());
+ FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);
+ CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
}
void Sema::setRoundingMode(SourceLocation Loc, llvm::RoundingMode FPR) {
- unsigned NewValue = FpPragmaStack.hasValue()
- ? FpPragmaStack.CurrentValue
- : CurFPFeatureOverrides().getAsOpaqueInt();
- FPOptionsOverride NewFPFeatures(NewValue);
+ // C2x: 7.6.2p3 If the FE_DYNAMIC mode is specified and FENV_ACCESS is "off",
+ // the translator may assume that the default rounding mode is in effect.
+ if (FPR == llvm::RoundingMode::Dynamic &&
+ !CurFPFeatures.getAllowFEnvAccess() &&
+ CurFPFeatures.getFPExceptionMode() == LangOptions::FPE_Ignore)
+ FPR = llvm::RoundingMode::NearestTiesToEven;
+
+ FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
NewFPFeatures.setRoundingModeOverride(FPR);
- NewValue = NewFPFeatures.getAsOpaqueInt();
- FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue);
- FPOptionsOverride NewOverrides(NewValue);
- CurFPFeatures = NewOverrides.applyOverrides(getLangOpts());
+ FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);
+ CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
}
void Sema::setExceptionMode(SourceLocation Loc,
LangOptions::FPExceptionModeKind FPE) {
- unsigned NewValue = FpPragmaStack.hasValue()
- ? FpPragmaStack.CurrentValue
- : CurFPFeatureOverrides().getAsOpaqueInt();
- FPOptionsOverride NewFPFeatures(NewValue);
+ FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
NewFPFeatures.setFPExceptionModeOverride(FPE);
- NewValue = NewFPFeatures.getAsOpaqueInt();
- FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue);
- FPOptionsOverride NewOverrides(NewValue);
- CurFPFeatures = NewOverrides.applyOverrides(getLangOpts());
+ FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);
+ CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
}
void Sema::ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled) {
- unsigned NewValue = FpPragmaStack.hasValue()
- ? FpPragmaStack.CurrentValue
- : CurFPFeatureOverrides().getAsOpaqueInt();
- FPOptionsOverride NewFPFeatures(NewValue);
+ FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
+ auto LO = getLangOpts();
if (IsEnabled) {
// Verify Microsoft restriction:
// You can't enable fenv_access unless precise semantics are enabled.
@@ -1038,12 +1123,20 @@ void Sema::ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled) {
if (!isPreciseFPEnabled())
Diag(Loc, diag::err_pragma_fenv_requires_precise);
NewFPFeatures.setAllowFEnvAccessOverride(true);
- } else
+ // Enabling FENV access sets the RoundingMode to Dynamic.
+ // and ExceptionBehavior to Strict
+ NewFPFeatures.setRoundingModeOverride(llvm::RoundingMode::Dynamic);
+ NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Strict);
+ } else {
NewFPFeatures.setAllowFEnvAccessOverride(false);
- NewValue = NewFPFeatures.getAsOpaqueInt();
- FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue);
- FPOptionsOverride NewOverrides(NewValue);
- CurFPFeatures = NewOverrides.applyOverrides(getLangOpts());
+ }
+ FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);
+ CurFPFeatures = NewFPFeatures.applyOverrides(LO);
+}
+
+void Sema::ActOnPragmaFPExceptions(SourceLocation Loc,
+ LangOptions::FPExceptionModeKind FPE) {
+ setExceptionMode(Loc, FPE);
}
void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp
index 283a04683a32..ee91eb4c5deb 100644
--- a/clang/lib/Sema/SemaCUDA.cpp
+++ b/clang/lib/Sema/SemaCUDA.cpp
@@ -123,7 +123,8 @@ Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D,
return CFT_Device;
} else if (hasAttr<CUDAHostAttr>(D, IgnoreImplicitHDAttr)) {
return CFT_Host;
- } else if (D->isImplicit() && !IgnoreImplicitHDAttr) {
+ } else if ((D->isImplicit() || !D->isUserProvided()) &&
+ !IgnoreImplicitHDAttr) {
// Some implicit declarations (like intrinsic functions) are not marked.
// Set the most lenient target on them for maximal flexibility.
return CFT_HostDevice;
@@ -519,7 +520,6 @@ void Sema::checkAllowedCUDAInitializer(VarDecl *VD) {
VD->hasAttr<CUDASharedAttr>()) {
if (LangOpts.GPUAllowDeviceInit)
return;
- assert(!VD->isStaticLocal() || VD->hasAttr<CUDASharedAttr>());
bool AllowedInit = false;
if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(Init))
AllowedInit =
@@ -639,58 +639,63 @@ void Sema::MaybeAddCUDAConstantAttr(VarDecl *VD) {
}
}
-Sema::DeviceDiagBuilder Sema::CUDADiagIfDeviceCode(SourceLocation Loc,
- unsigned DiagID) {
+Sema::SemaDiagnosticBuilder Sema::CUDADiagIfDeviceCode(SourceLocation Loc,
+ unsigned DiagID) {
assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
- DeviceDiagBuilder::Kind DiagKind = [this] {
+ SemaDiagnosticBuilder::Kind DiagKind = [&] {
+ if (!isa<FunctionDecl>(CurContext))
+ return SemaDiagnosticBuilder::K_Nop;
switch (CurrentCUDATarget()) {
case CFT_Global:
case CFT_Device:
- return DeviceDiagBuilder::K_Immediate;
+ return SemaDiagnosticBuilder::K_Immediate;
case CFT_HostDevice:
// An HD function counts as host code if we're compiling for host, and
// device code if we're compiling for device. Defer any errors in device
// mode until the function is known-emitted.
- if (getLangOpts().CUDAIsDevice) {
- return (getEmissionStatus(cast<FunctionDecl>(CurContext)) ==
- FunctionEmissionStatus::Emitted)
- ? DeviceDiagBuilder::K_ImmediateWithCallStack
- : DeviceDiagBuilder::K_Deferred;
- }
- return DeviceDiagBuilder::K_Nop;
-
+ if (!getLangOpts().CUDAIsDevice)
+ return SemaDiagnosticBuilder::K_Nop;
+ if (IsLastErrorImmediate && Diags.getDiagnosticIDs()->isBuiltinNote(DiagID))
+ return SemaDiagnosticBuilder::K_Immediate;
+ return (getEmissionStatus(cast<FunctionDecl>(CurContext)) ==
+ FunctionEmissionStatus::Emitted)
+ ? SemaDiagnosticBuilder::K_ImmediateWithCallStack
+ : SemaDiagnosticBuilder::K_Deferred;
default:
- return DeviceDiagBuilder::K_Nop;
+ return SemaDiagnosticBuilder::K_Nop;
}
}();
- return DeviceDiagBuilder(DiagKind, Loc, DiagID,
- dyn_cast<FunctionDecl>(CurContext), *this);
+ return SemaDiagnosticBuilder(DiagKind, Loc, DiagID,
+ dyn_cast<FunctionDecl>(CurContext), *this);
}
-Sema::DeviceDiagBuilder Sema::CUDADiagIfHostCode(SourceLocation Loc,
- unsigned DiagID) {
+Sema::SemaDiagnosticBuilder Sema::CUDADiagIfHostCode(SourceLocation Loc,
+ unsigned DiagID) {
assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
- DeviceDiagBuilder::Kind DiagKind = [this] {
+ SemaDiagnosticBuilder::Kind DiagKind = [&] {
+ if (!isa<FunctionDecl>(CurContext))
+ return SemaDiagnosticBuilder::K_Nop;
switch (CurrentCUDATarget()) {
case CFT_Host:
- return DeviceDiagBuilder::K_Immediate;
+ return SemaDiagnosticBuilder::K_Immediate;
case CFT_HostDevice:
// An HD function counts as host code if we're compiling for host, and
// device code if we're compiling for device. Defer any errors in device
// mode until the function is known-emitted.
if (getLangOpts().CUDAIsDevice)
- return DeviceDiagBuilder::K_Nop;
-
+ return SemaDiagnosticBuilder::K_Nop;
+ if (IsLastErrorImmediate && Diags.getDiagnosticIDs()->isBuiltinNote(DiagID))
+ return SemaDiagnosticBuilder::K_Immediate;
return (getEmissionStatus(cast<FunctionDecl>(CurContext)) ==
FunctionEmissionStatus::Emitted)
- ? DeviceDiagBuilder::K_ImmediateWithCallStack
- : DeviceDiagBuilder::K_Deferred;
+ ? SemaDiagnosticBuilder::K_ImmediateWithCallStack
+ : SemaDiagnosticBuilder::K_Deferred;
default:
- return DeviceDiagBuilder::K_Nop;
+ return SemaDiagnosticBuilder::K_Nop;
}
}();
- return DeviceDiagBuilder(DiagKind, Loc, DiagID,
- dyn_cast<FunctionDecl>(CurContext), *this);
+ return SemaDiagnosticBuilder(DiagKind, Loc, DiagID,
+ dyn_cast<FunctionDecl>(CurContext), *this);
}
bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) {
@@ -711,24 +716,24 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) {
// Otherwise, mark the call in our call graph so we can traverse it later.
bool CallerKnownEmitted =
getEmissionStatus(Caller) == FunctionEmissionStatus::Emitted;
- DeviceDiagBuilder::Kind DiagKind = [this, Caller, Callee,
- CallerKnownEmitted] {
+ SemaDiagnosticBuilder::Kind DiagKind = [this, Caller, Callee,
+ CallerKnownEmitted] {
switch (IdentifyCUDAPreference(Caller, Callee)) {
case CFP_Never:
- return DeviceDiagBuilder::K_Immediate;
case CFP_WrongSide:
- assert(Caller && "WrongSide calls require a non-null caller");
+ assert(Caller && "Never/wrongSide calls require a non-null caller");
// If we know the caller will be emitted, we know this wrong-side call
// will be emitted, so it's an immediate error. Otherwise, defer the
// error until we know the caller is emitted.
- return CallerKnownEmitted ? DeviceDiagBuilder::K_ImmediateWithCallStack
- : DeviceDiagBuilder::K_Deferred;
+ return CallerKnownEmitted
+ ? SemaDiagnosticBuilder::K_ImmediateWithCallStack
+ : SemaDiagnosticBuilder::K_Deferred;
default:
- return DeviceDiagBuilder::K_Nop;
+ return SemaDiagnosticBuilder::K_Nop;
}
}();
- if (DiagKind == DeviceDiagBuilder::K_Nop)
+ if (DiagKind == SemaDiagnosticBuilder::K_Nop)
return true;
// Avoid emitting this error twice for the same location. Using a hashtable
@@ -738,13 +743,15 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) {
if (!LocsWithCUDACallDiags.insert({Caller, Loc}).second)
return true;
- DeviceDiagBuilder(DiagKind, Loc, diag::err_ref_bad_target, Caller, *this)
- << IdentifyCUDATarget(Callee) << Callee << IdentifyCUDATarget(Caller);
- DeviceDiagBuilder(DiagKind, Callee->getLocation(), diag::note_previous_decl,
- Caller, *this)
- << Callee;
- return DiagKind != DeviceDiagBuilder::K_Immediate &&
- DiagKind != DeviceDiagBuilder::K_ImmediateWithCallStack;
+ SemaDiagnosticBuilder(DiagKind, Loc, diag::err_ref_bad_target, Caller, *this)
+ << IdentifyCUDATarget(Callee) << /*function*/ 0 << Callee
+ << IdentifyCUDATarget(Caller);
+ if (!Callee->getBuiltinID())
+ SemaDiagnosticBuilder(DiagKind, Callee->getLocation(),
+ diag::note_previous_decl, Caller, *this)
+ << Callee;
+ return DiagKind != SemaDiagnosticBuilder::K_Immediate &&
+ DiagKind != SemaDiagnosticBuilder::K_ImmediateWithCallStack;
}
// Check the wrong-sided reference capture of lambda for CUDA/HIP.
@@ -781,14 +788,14 @@ void Sema::CUDACheckLambdaCapture(CXXMethodDecl *Callee,
bool ShouldCheck = CalleeIsDevice && CallerIsHost;
if (!ShouldCheck || !Capture.isReferenceCapture())
return;
- auto DiagKind = DeviceDiagBuilder::K_Deferred;
+ auto DiagKind = SemaDiagnosticBuilder::K_Deferred;
if (Capture.isVariableCapture()) {
- DeviceDiagBuilder(DiagKind, Capture.getLocation(),
- diag::err_capture_bad_target, Callee, *this)
+ SemaDiagnosticBuilder(DiagKind, Capture.getLocation(),
+ diag::err_capture_bad_target, Callee, *this)
<< Capture.getVariable();
} else if (Capture.isThisCapture()) {
- DeviceDiagBuilder(DiagKind, Capture.getLocation(),
- diag::err_capture_bad_target_this_ptr, Callee, *this);
+ SemaDiagnosticBuilder(DiagKind, Capture.getLocation(),
+ diag::err_capture_bad_target_this_ptr, Callee, *this);
}
return;
}
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index 2efe26052c78..671820afd485 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -105,10 +105,10 @@ namespace {
// If this is an unbridged cast, wrap the result in an implicit
// cast that yields the unbridged-cast placeholder type.
if (IsARCUnbridgedCast) {
- castExpr = ImplicitCastExpr::Create(Self.Context,
- Self.Context.ARCUnbridgedCastTy,
- CK_Dependent, castExpr, nullptr,
- castExpr->getValueKind());
+ castExpr = ImplicitCastExpr::Create(
+ Self.Context, Self.Context.ARCUnbridgedCastTy, CK_Dependent,
+ castExpr, nullptr, castExpr->getValueKind(),
+ Self.CurFPFeatureOverrides());
}
updatePartOfExplicitCastFlags(castExpr);
return castExpr;
@@ -361,11 +361,10 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
DiscardMisalignedMemberAddress(DestType.getTypePtr(), E);
}
- return Op.complete(CXXStaticCastExpr::Create(Context, Op.ResultType,
- Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
- &Op.BasePath, DestTInfo,
- OpLoc, Parens.getEnd(),
- AngleBrackets));
+ return Op.complete(CXXStaticCastExpr::Create(
+ Context, Op.ResultType, Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
+ &Op.BasePath, DestTInfo, CurFPFeatureOverrides(), OpLoc,
+ Parens.getEnd(), AngleBrackets));
}
}
}
@@ -510,12 +509,10 @@ static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType,
if (RecFrom && RecTo) {
auto DeclFrom = RecFrom->getAsCXXRecordDecl();
if (!DeclFrom->isCompleteDefinition())
- S.Diag(DeclFrom->getLocation(), diag::note_type_incomplete)
- << DeclFrom->getDeclName();
+ S.Diag(DeclFrom->getLocation(), diag::note_type_incomplete) << DeclFrom;
auto DeclTo = RecTo->getAsCXXRecordDecl();
if (!DeclTo->isCompleteDefinition())
- S.Diag(DeclTo->getLocation(), diag::note_type_incomplete)
- << DeclTo->getDeclName();
+ S.Diag(DeclTo->getLocation(), diag::note_type_incomplete) << DeclTo;
}
}
}
@@ -892,6 +889,18 @@ void CastOperation::CheckDynamicCast() {
return;
}
+ // Warns when dynamic_cast is used with RTTI data disabled.
+ if (!Self.getLangOpts().RTTIData) {
+ bool MicrosoftABI =
+ Self.getASTContext().getTargetInfo().getCXXABI().isMicrosoft();
+ bool isClangCL = Self.getDiagnostics().getDiagnosticOptions().getFormat() ==
+ DiagnosticOptions::MSVC;
+ if (MicrosoftABI || !DestPointee->isVoidType())
+ Self.Diag(OpRange.getBegin(),
+ diag::warn_no_dynamic_cast_with_rtti_disabled)
+ << isClangCL;
+ }
+
// Done. Everything else is run-time checks.
Kind = CK_Dynamic;
}
@@ -1245,7 +1254,13 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
return TC_Failed;
}
if (SrcType->isIntegralOrEnumerationType()) {
- Kind = CK_IntegralCast;
+ // [expr.static.cast]p10 If the enumeration type has a fixed underlying
+ // type, the value is first converted to that type by integral conversion
+ const EnumType *Enum = DestType->getAs<EnumType>();
+ Kind = Enum->getDecl()->isFixed() &&
+ Enum->getDecl()->getIntegerType()->isBooleanType()
+ ? CK_IntegralToBoolean
+ : CK_IntegralCast;
return TC_Success;
} else if (SrcType->isRealFloatingType()) {
Kind = CK_FloatingToIntegral;
@@ -2204,6 +2219,12 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
bool destIsVector = DestType->isVectorType();
bool srcIsVector = SrcType->isVectorType();
if (srcIsVector || destIsVector) {
+ // Allow bitcasting between SVE VLATs and VLSTs, and vice-versa.
+ if (Self.isValidSveBitcast(SrcType, DestType)) {
+ Kind = CK_BitCast;
+ return TC_Success;
+ }
+
// The non-vector type, if any, must have integral type. This is
// the same rule that C vector casts use; note, however, that enum
// types are not integral in C++.
@@ -2659,6 +2680,8 @@ static void DiagnoseBadFunctionCast(Sema &Self, const ExprResult &SrcExpr,
return;
if (SrcType->isComplexIntegerType() && DestType->isComplexIntegerType())
return;
+ if (SrcType->isFixedPointType() && DestType->isFixedPointType())
+ return;
Self.Diag(SrcExpr.get()->getExprLoc(),
diag::warn_bad_function_cast)
@@ -2690,6 +2713,17 @@ void CastOperation::CheckCStyleCast() {
return;
}
+ // If the type is dependent, we won't do any other semantic analysis now.
+ if (Self.getASTContext().isDependenceAllowed() &&
+ (DestType->isDependentType() || SrcExpr.get()->isTypeDependent() ||
+ SrcExpr.get()->isValueDependent())) {
+ assert((DestType->containsErrors() || SrcExpr.get()->containsErrors() ||
+ SrcExpr.get()->containsErrors()) &&
+ "should only occur in error-recovery path.");
+ assert(Kind == CK_Dependent);
+ return;
+ }
+
// Overloads are allowed with C extensions, so we need to support them.
if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
DeclAccessPair DAP;
@@ -2724,6 +2758,13 @@ void CastOperation::CheckCStyleCast() {
return;
}
+ // Allow bitcasting between compatible SVE vector types.
+ if ((SrcType->isVectorType() || DestType->isVectorType()) &&
+ Self.isValidSveBitcast(SrcType, DestType)) {
+ Kind = CK_BitCast;
+ return;
+ }
+
if (!DestType->isScalarType() && !DestType->isVectorType()) {
const RecordType *DestRecordTy = DestType->getAs<RecordType>();
@@ -3027,9 +3068,9 @@ ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc,
// -Wcast-qual
DiagnoseCastQual(Op.Self, Op.SrcExpr, Op.DestType);
- return Op.complete(CStyleCastExpr::Create(Context, Op.ResultType,
- Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
- &Op.BasePath, CastTypeInfo, LPLoc, RPLoc));
+ return Op.complete(CStyleCastExpr::Create(
+ Context, Op.ResultType, Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
+ &Op.BasePath, CurFPFeatureOverrides(), CastTypeInfo, LPLoc, RPLoc));
}
ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
@@ -3052,7 +3093,7 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
if (auto *ConstructExpr = dyn_cast<CXXConstructExpr>(SubExpr))
ConstructExpr->setParenOrBraceRange(SourceRange(LPLoc, RPLoc));
- return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType,
- Op.ValueKind, CastTypeInfo, Op.Kind,
- Op.SrcExpr.get(), &Op.BasePath, LPLoc, RPLoc));
+ return Op.complete(CXXFunctionalCastExpr::Create(
+ Context, Op.ResultType, Op.ValueKind, CastTypeInfo, Op.Kind,
+ Op.SrcExpr.get(), &Op.BasePath, CurFPFeatureOverrides(), LPLoc, RPLoc));
}
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 509d88e25000..2d3d36f4adad 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -75,6 +75,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/AtomicOrdering.h"
@@ -1274,11 +1275,8 @@ static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) {
// \return True if a semantic error has been found, false otherwise.
static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID,
CallExpr *Call) {
- if (Call->getNumArgs() != 1) {
- S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_to_addr_arg_num)
- << Call->getDirectCallee() << Call->getSourceRange();
+ if (checkArgCount(S, Call, 1))
return true;
- }
auto RT = Call->getArg(0)->getType();
if (!RT->isPointerType() || RT->getPointeeType()
@@ -1425,6 +1423,7 @@ bool Sema::CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
case llvm::Triple::x86_64:
return CheckX86BuiltinFunctionCall(TI, BuiltinID, TheCall);
case llvm::Triple::ppc:
+ case llvm::Triple::ppcle:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
return CheckPPCBuiltinFunctionCall(TI, BuiltinID, TheCall);
@@ -1573,15 +1572,14 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
if (SemaBuiltinSetjmp(TheCall))
return ExprError();
break;
- case Builtin::BI_setjmp:
- case Builtin::BI_setjmpex:
- if (checkArgCount(*this, TheCall, 1))
- return true;
- break;
case Builtin::BI__builtin_classify_type:
if (checkArgCount(*this, TheCall, 1)) return true;
TheCall->setType(Context.IntTy);
break;
+ case Builtin::BI__builtin_complex:
+ if (SemaBuiltinComplex(TheCall))
+ return ExprError();
+ break;
case Builtin::BI__builtin_constant_p: {
if (checkArgCount(*this, TheCall, 1)) return true;
ExprResult Arg = DefaultFunctionArrayLvalueConversion(TheCall->getArg(0));
@@ -1818,8 +1816,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
SmallVector<PartialDiagnosticAt, 8> Notes;
Expr::EvalResult Eval;
Eval.Diag = &Notes;
- if ((!ProbArg->EvaluateAsConstantExpr(Eval, Expr::EvaluateForCodeGen,
- Context)) ||
+ if ((!ProbArg->EvaluateAsConstantExpr(Eval, Context)) ||
!Eval.Val.isFloat()) {
Diag(ProbArg->getBeginLoc(), diag::err_probability_not_constant_float)
<< ProbArg->getSourceRange();
@@ -1946,7 +1943,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
// -Wframe-address warning if non-zero passed to builtin
// return/frame address.
Expr::EvalResult Result;
- if (TheCall->getArg(0)->EvaluateAsInt(Result, getASTContext()) &&
+ if (!TheCall->getArg(0)->isValueDependent() &&
+ TheCall->getArg(0)->EvaluateAsInt(Result, getASTContext()) &&
Result.Val.getInt() != 0)
Diag(TheCall->getBeginLoc(), diag::warn_frame_address)
<< ((BuiltinID == Builtin::BI__builtin_return_address)
@@ -2284,10 +2282,7 @@ bool Sema::CheckARMCoprocessorImmediate(const TargetInfo &TI,
if (CoprocArg->isTypeDependent() || CoprocArg->isValueDependent())
return false;
- llvm::APSInt CoprocNoAP;
- bool IsICE = CoprocArg->isIntegerConstantExpr(CoprocNoAP, Context);
- (void)IsICE;
- assert(IsICE && "Coprocossor immediate is not a constant expression");
+ llvm::APSInt CoprocNoAP = *CoprocArg->getIntegerConstantExpr(Context);
int64_t CoprocNo = CoprocNoAP.getExtValue();
assert(CoprocNo >= 0 && "Coprocessor immediate must be non-negative");
@@ -2559,54 +2554,164 @@ bool Sema::CheckAArch64BuiltinFunctionCall(const TargetInfo &TI,
return SemaBuiltinConstantArgRange(TheCall, i, l, u + l);
}
-bool Sema::CheckBPFBuiltinFunctionCall(unsigned BuiltinID,
- CallExpr *TheCall) {
- assert((BuiltinID == BPF::BI__builtin_preserve_field_info ||
- BuiltinID == BPF::BI__builtin_btf_type_id) &&
- "unexpected ARM builtin");
+static bool isValidBPFPreserveFieldInfoArg(Expr *Arg) {
+ if (Arg->getType()->getAsPlaceholderType())
+ return false;
- if (checkArgCount(*this, TheCall, 2))
+ // The first argument needs to be a record field access.
+ // If it is an array element access, we delay decision
+ // to BPF backend to check whether the access is a
+ // field access or not.
+ return (Arg->IgnoreParens()->getObjectKind() == OK_BitField ||
+ dyn_cast<MemberExpr>(Arg->IgnoreParens()) ||
+ dyn_cast<ArraySubscriptExpr>(Arg->IgnoreParens()));
+}
+
+static bool isEltOfVectorTy(ASTContext &Context, CallExpr *Call, Sema &S,
+ QualType VectorTy, QualType EltTy) {
+ QualType VectorEltTy = VectorTy->castAs<VectorType>()->getElementType();
+ if (!Context.hasSameType(VectorEltTy, EltTy)) {
+ S.Diag(Call->getBeginLoc(), diag::err_typecheck_call_different_arg_types)
+ << Call->getSourceRange() << VectorEltTy << EltTy;
+ return false;
+ }
+ return true;
+}
+
+static bool isValidBPFPreserveTypeInfoArg(Expr *Arg) {
+ QualType ArgType = Arg->getType();
+ if (ArgType->getAsPlaceholderType())
+ return false;
+
+ // for TYPE_EXISTENCE/TYPE_SIZEOF reloc type
+ // format:
+ // 1. __builtin_preserve_type_info(*(<type> *)0, flag);
+ // 2. <type> var;
+ // __builtin_preserve_type_info(var, flag);
+ if (!dyn_cast<DeclRefExpr>(Arg->IgnoreParens()) &&
+ !dyn_cast<UnaryOperator>(Arg->IgnoreParens()))
+ return false;
+
+ // Typedef type.
+ if (ArgType->getAs<TypedefType>())
return true;
- Expr *Arg;
- if (BuiltinID == BPF::BI__builtin_btf_type_id) {
- // The second argument needs to be a constant int
- llvm::APSInt Value;
- Arg = TheCall->getArg(1);
- if (!Arg->isIntegerConstantExpr(Value, Context)) {
- Diag(Arg->getBeginLoc(), diag::err_btf_type_id_not_const)
- << 2 << Arg->getSourceRange();
+ // Record type or Enum type.
+ const Type *Ty = ArgType->getUnqualifiedDesugaredType();
+ if (const auto *RT = Ty->getAs<RecordType>()) {
+ if (!RT->getDecl()->getDeclName().isEmpty())
return true;
- }
+ } else if (const auto *ET = Ty->getAs<EnumType>()) {
+ if (!ET->getDecl()->getDeclName().isEmpty())
+ return true;
+ }
- TheCall->setType(Context.UnsignedIntTy);
+ return false;
+}
+
+static bool isValidBPFPreserveEnumValueArg(Expr *Arg) {
+ QualType ArgType = Arg->getType();
+ if (ArgType->getAsPlaceholderType())
+ return false;
+
+ // for ENUM_VALUE_EXISTENCE/ENUM_VALUE reloc type
+ // format:
+ // __builtin_preserve_enum_value(*(<enum_type> *)<enum_value>,
+ // flag);
+ const auto *UO = dyn_cast<UnaryOperator>(Arg->IgnoreParens());
+ if (!UO)
+ return false;
+
+ const auto *CE = dyn_cast<CStyleCastExpr>(UO->getSubExpr());
+ if (!CE || CE->getCastKind() != CK_IntegralToPointer)
+ return false;
+
+ // The integer must be from an EnumConstantDecl.
+ const auto *DR = dyn_cast<DeclRefExpr>(CE->getSubExpr());
+ if (!DR)
+ return false;
+
+ const EnumConstantDecl *Enumerator =
+ dyn_cast<EnumConstantDecl>(DR->getDecl());
+ if (!Enumerator)
+ return false;
+
+ // The type must be EnumType.
+ const Type *Ty = ArgType->getUnqualifiedDesugaredType();
+ const auto *ET = Ty->getAs<EnumType>();
+ if (!ET)
return false;
+
+ // The enum value must be supported.
+ for (auto *EDI : ET->getDecl()->enumerators()) {
+ if (EDI == Enumerator)
+ return true;
}
- // The first argument needs to be a record field access.
- // If it is an array element access, we delay decision
- // to BPF backend to check whether the access is a
- // field access or not.
- Arg = TheCall->getArg(0);
- if (Arg->getType()->getAsPlaceholderType() ||
- (Arg->IgnoreParens()->getObjectKind() != OK_BitField &&
- !dyn_cast<MemberExpr>(Arg->IgnoreParens()) &&
- !dyn_cast<ArraySubscriptExpr>(Arg->IgnoreParens()))) {
- Diag(Arg->getBeginLoc(), diag::err_preserve_field_info_not_field)
- << 1 << Arg->getSourceRange();
+ return false;
+}
+
+bool Sema::CheckBPFBuiltinFunctionCall(unsigned BuiltinID,
+ CallExpr *TheCall) {
+ assert((BuiltinID == BPF::BI__builtin_preserve_field_info ||
+ BuiltinID == BPF::BI__builtin_btf_type_id ||
+ BuiltinID == BPF::BI__builtin_preserve_type_info ||
+ BuiltinID == BPF::BI__builtin_preserve_enum_value) &&
+ "unexpected BPF builtin");
+
+ if (checkArgCount(*this, TheCall, 2))
return true;
- }
// The second argument needs to be a constant int
- Arg = TheCall->getArg(1);
- llvm::APSInt Value;
- if (!Arg->isIntegerConstantExpr(Value, Context)) {
- Diag(Arg->getBeginLoc(), diag::err_preserve_field_info_not_const)
- << 2 << Arg->getSourceRange();
+ Expr *Arg = TheCall->getArg(1);
+ Optional<llvm::APSInt> Value = Arg->getIntegerConstantExpr(Context);
+ diag::kind kind;
+ if (!Value) {
+ if (BuiltinID == BPF::BI__builtin_preserve_field_info)
+ kind = diag::err_preserve_field_info_not_const;
+ else if (BuiltinID == BPF::BI__builtin_btf_type_id)
+ kind = diag::err_btf_type_id_not_const;
+ else if (BuiltinID == BPF::BI__builtin_preserve_type_info)
+ kind = diag::err_preserve_type_info_not_const;
+ else
+ kind = diag::err_preserve_enum_value_not_const;
+ Diag(Arg->getBeginLoc(), kind) << 2 << Arg->getSourceRange();
return true;
}
- TheCall->setType(Context.UnsignedIntTy);
+ // The first argument
+ Arg = TheCall->getArg(0);
+ bool InvalidArg = false;
+ bool ReturnUnsignedInt = true;
+ if (BuiltinID == BPF::BI__builtin_preserve_field_info) {
+ if (!isValidBPFPreserveFieldInfoArg(Arg)) {
+ InvalidArg = true;
+ kind = diag::err_preserve_field_info_not_field;
+ }
+ } else if (BuiltinID == BPF::BI__builtin_preserve_type_info) {
+ if (!isValidBPFPreserveTypeInfoArg(Arg)) {
+ InvalidArg = true;
+ kind = diag::err_preserve_type_info_invalid;
+ }
+ } else if (BuiltinID == BPF::BI__builtin_preserve_enum_value) {
+ if (!isValidBPFPreserveEnumValueArg(Arg)) {
+ InvalidArg = true;
+ kind = diag::err_preserve_enum_value_invalid;
+ }
+ ReturnUnsignedInt = false;
+ } else if (BuiltinID == BPF::BI__builtin_btf_type_id) {
+ ReturnUnsignedInt = false;
+ }
+
+ if (InvalidArg) {
+ Diag(Arg->getBeginLoc(), kind) << 1 << Arg->getSourceRange();
+ return true;
+ }
+
+ if (ReturnUnsignedInt)
+ TheCall->setType(Context.UnsignedIntTy);
+ else
+ TheCall->setType(Context.UnsignedLongTy);
return false;
}
@@ -3067,6 +3172,62 @@ bool Sema::CheckMipsBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall) {
SemaBuiltinConstantArgMultiple(TheCall, i, m);
}
+/// DecodePPCMMATypeFromStr - This decodes one PPC MMA type descriptor from Str,
+/// advancing the pointer over the consumed characters. The decoded type is
+/// returned. If the decoded type represents a constant integer with a
+/// constraint on its value then Mask is set to that value. The type descriptors
+/// used in Str are specific to PPC MMA builtins and are documented in the file
+/// defining the PPC builtins.
+static QualType DecodePPCMMATypeFromStr(ASTContext &Context, const char *&Str,
+ unsigned &Mask) {
+ bool RequireICE = false;
+ ASTContext::GetBuiltinTypeError Error = ASTContext::GE_None;
+ switch (*Str++) {
+ case 'V':
+ return Context.getVectorType(Context.UnsignedCharTy, 16,
+ VectorType::VectorKind::AltiVecVector);
+ case 'i': {
+ char *End;
+ unsigned size = strtoul(Str, &End, 10);
+ assert(End != Str && "Missing constant parameter constraint");
+ Str = End;
+ Mask = size;
+ return Context.IntTy;
+ }
+ case 'W': {
+ char *End;
+ unsigned size = strtoul(Str, &End, 10);
+ assert(End != Str && "Missing PowerPC MMA type size");
+ Str = End;
+ QualType Type;
+ switch (size) {
+ #define PPC_VECTOR_TYPE(typeName, Id, size) \
+ case size: Type = Context.Id##Ty; break;
+ #include "clang/Basic/PPCTypes.def"
+ default: llvm_unreachable("Invalid PowerPC MMA vector type");
+ }
+ bool CheckVectorArgs = false;
+ while (!CheckVectorArgs) {
+ switch (*Str++) {
+ case '*':
+ Type = Context.getPointerType(Type);
+ break;
+ case 'C':
+ Type = Type.withConst();
+ break;
+ default:
+ CheckVectorArgs = true;
+ --Str;
+ break;
+ }
+ }
+ return Type;
+ }
+ default:
+ return Context.DecodeTypeStr(--Str, Context, Error, RequireICE, true);
+ }
+}
+
bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall) {
unsigned i = 0, l = 0, u = 0;
@@ -3127,6 +3288,14 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
return SemaVSXCheck(TheCall);
case PPC::BI__builtin_altivec_vgnb:
return SemaBuiltinConstantArgRange(TheCall, 1, 2, 7);
+ case PPC::BI__builtin_altivec_vec_replace_elt:
+ case PPC::BI__builtin_altivec_vec_replace_unaligned: {
+ QualType VecTy = TheCall->getArg(0)->getType();
+ QualType EltTy = TheCall->getArg(1)->getType();
+ unsigned Width = Context.getIntWidth(EltTy);
+ return SemaBuiltinConstantArgRange(TheCall, 2, 0, Width == 32 ? 12 : 8) ||
+ !isEltOfVectorTy(Context, TheCall, *this, VecTy, EltTy);
+ }
case PPC::BI__builtin_vsx_xxeval:
return SemaBuiltinConstantArgRange(TheCall, 3, 0, 255);
case PPC::BI__builtin_altivec_vsldbi:
@@ -3135,10 +3304,31 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
return SemaBuiltinConstantArgRange(TheCall, 2, 0, 7);
case PPC::BI__builtin_vsx_xxpermx:
return SemaBuiltinConstantArgRange(TheCall, 3, 0, 7);
+#define CUSTOM_BUILTIN(Name, Types, Acc) \
+ case PPC::BI__builtin_##Name: \
+ return SemaBuiltinPPCMMACall(TheCall, Types);
+#include "clang/Basic/BuiltinsPPC.def"
}
return SemaBuiltinConstantArgRange(TheCall, i, l, u);
}
+// Check if the given type is a non-pointer PPC MMA type. This function is used
+// in Sema to prevent invalid uses of restricted PPC MMA types.
+bool Sema::CheckPPCMMAType(QualType Type, SourceLocation TypeLoc) {
+ if (Type->isPointerType() || Type->isArrayType())
+ return false;
+
+ QualType CoreType = Type.getCanonicalType().getUnqualifiedType();
+#define PPC_VECTOR_TYPE(Name, Id, Size) || CoreType == Context.Id##Ty
+ if (false
+#include "clang/Basic/PPCTypes.def"
+ ) {
+ Diag(TypeLoc, diag::err_ppc_invalid_use_mma_type);
+ return true;
+ }
+ return false;
+}
+
bool Sema::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID,
CallExpr *TheCall) {
// position of memory order and scope arguments in the builtin
@@ -3186,8 +3376,7 @@ bool Sema::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID,
ArgExpr = Arg.get();
Expr::EvalResult ArgResult1;
// Check that sync scope is a constant literal
- if (!ArgExpr->EvaluateAsConstantExpr(ArgResult1, Expr::EvaluateForCodeGen,
- Context))
+ if (!ArgExpr->EvaluateAsConstantExpr(ArgResult1, Context))
return Diag(ArgExpr->getExprLoc(), diag::err_expr_not_string_literal)
<< ArgExpr->getType();
@@ -3198,11 +3387,10 @@ bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID,
CallExpr *TheCall) {
if (BuiltinID == SystemZ::BI__builtin_tabort) {
Expr *Arg = TheCall->getArg(0);
- llvm::APSInt AbortCode(32);
- if (Arg->isIntegerConstantExpr(AbortCode, Context) &&
- AbortCode.getSExtValue() >= 0 && AbortCode.getSExtValue() < 256)
- return Diag(Arg->getBeginLoc(), diag::err_systemz_invalid_tabort_code)
- << Arg->getSourceRange();
+ if (Optional<llvm::APSInt> AbortCode = Arg->getIntegerConstantExpr(Context))
+ if (AbortCode->getSExtValue() >= 0 && AbortCode->getSExtValue() < 256)
+ return Diag(Arg->getBeginLoc(), diag::err_systemz_invalid_tabort_code)
+ << Arg->getSourceRange();
}
// For intrinsics which take an immediate value as part of the instruction,
@@ -3611,7 +3799,7 @@ bool Sema::CheckX86BuiltinGatherScatterScale(unsigned BuiltinID,
enum { TileRegLow = 0, TileRegHigh = 7 };
bool Sema::CheckX86BuiltinTileArgumentsRange(CallExpr *TheCall,
- ArrayRef<int> ArgNums) {
+ ArrayRef<int> ArgNums) {
for (int ArgNum : ArgNums) {
if (SemaBuiltinConstantArgRange(TheCall, ArgNum, TileRegLow, TileRegHigh))
return true;
@@ -3619,19 +3807,20 @@ bool Sema::CheckX86BuiltinTileArgumentsRange(CallExpr *TheCall,
return false;
}
-bool Sema::CheckX86BuiltinTileArgumentsRange(CallExpr *TheCall, int ArgNum) {
- return SemaBuiltinConstantArgRange(TheCall, ArgNum, TileRegLow, TileRegHigh);
-}
-
bool Sema::CheckX86BuiltinTileDuplicate(CallExpr *TheCall,
ArrayRef<int> ArgNums) {
// Because the max number of tile register is TileRegHigh + 1, so here we use
// each bit to represent the usage of them in bitset.
std::bitset<TileRegHigh + 1> ArgValues;
for (int ArgNum : ArgNums) {
- llvm::APSInt Arg;
- SemaBuiltinConstantArg(TheCall, ArgNum, Arg);
- int ArgExtValue = Arg.getExtValue();
+ Expr *Arg = TheCall->getArg(ArgNum);
+ if (Arg->isTypeDependent() || Arg->isValueDependent())
+ continue;
+
+ llvm::APSInt Result;
+ if (SemaBuiltinConstantArg(TheCall, ArgNum, Result))
+ return true;
+ int ArgExtValue = Result.getExtValue();
assert((ArgExtValue >= TileRegLow || ArgExtValue <= TileRegHigh) &&
"Incorrect tile register num.");
if (ArgValues.test(ArgExtValue))
@@ -4382,6 +4571,8 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
if (!FnInfo)
return false;
+ CheckTCBEnforcement(TheCall, FDecl);
+
CheckAbsoluteValueFunction(TheCall, FDecl);
CheckMaxUnsignedZero(TheCall, FDecl);
@@ -4389,16 +4580,24 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
DiagnoseCStringFormatDirectiveInCFAPI(*this, FDecl, Args, NumArgs);
unsigned CMId = FDecl->getMemoryFunctionKind();
- if (CMId == 0)
- return false;
// Handle memory setting and copying functions.
- if (CMId == Builtin::BIstrlcpy || CMId == Builtin::BIstrlcat)
+ switch (CMId) {
+ case 0:
+ return false;
+ case Builtin::BIstrlcpy: // fallthrough
+ case Builtin::BIstrlcat:
CheckStrlcpycatArguments(TheCall, FnInfo);
- else if (CMId == Builtin::BIstrncat)
+ break;
+ case Builtin::BIstrncat:
CheckStrncatArguments(TheCall, FnInfo);
- else
+ break;
+ case Builtin::BIfree:
+ CheckFreeArguments(TheCall);
+ break;
+ default:
CheckMemaccessArguments(TheCall, CMId, FnInfo);
+ }
return false;
}
@@ -4923,21 +5122,21 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
}
if (SubExprs.size() >= 2 && Form != Init) {
- llvm::APSInt Result(32);
- if (SubExprs[1]->isIntegerConstantExpr(Result, Context) &&
- !isValidOrderingForOp(Result.getSExtValue(), Op))
- Diag(SubExprs[1]->getBeginLoc(),
- diag::warn_atomic_op_has_invalid_memory_order)
- << SubExprs[1]->getSourceRange();
+ if (Optional<llvm::APSInt> Result =
+ SubExprs[1]->getIntegerConstantExpr(Context))
+ if (!isValidOrderingForOp(Result->getSExtValue(), Op))
+ Diag(SubExprs[1]->getBeginLoc(),
+ diag::warn_atomic_op_has_invalid_memory_order)
+ << SubExprs[1]->getSourceRange();
}
if (auto ScopeModel = AtomicExpr::getScopeModel(Op)) {
auto *Scope = Args[Args.size() - 1];
- llvm::APSInt Result(32);
- if (Scope->isIntegerConstantExpr(Result, Context) &&
- !ScopeModel->isValid(Result.getZExtValue())) {
- Diag(Scope->getBeginLoc(), diag::err_atomic_op_has_invalid_synch_scope)
- << Scope->getSourceRange();
+ if (Optional<llvm::APSInt> Result =
+ Scope->getIntegerConstantExpr(Context)) {
+ if (!ScopeModel->isValid(Result->getZExtValue()))
+ Diag(Scope->getBeginLoc(), diag::err_atomic_op_has_invalid_synch_scope)
+ << Scope->getSourceRange();
}
SubExprs.push_back(Scope);
}
@@ -4956,6 +5155,11 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
? 0
: 1);
+ if (ValType->isExtIntType()) {
+ Diag(Ptr->getExprLoc(), diag::err_atomic_builtin_ext_int_prohibit);
+ return ExprError();
+ }
+
return AE;
}
@@ -5574,21 +5778,8 @@ bool Sema::SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) {
if (checkVAStartABI(*this, BuiltinID, Fn))
return true;
- if (TheCall->getNumArgs() > 2) {
- Diag(TheCall->getArg(2)->getBeginLoc(),
- diag::err_typecheck_call_too_many_args)
- << 0 /*function call*/ << 2 << TheCall->getNumArgs()
- << Fn->getSourceRange()
- << SourceRange(TheCall->getArg(2)->getBeginLoc(),
- (*(TheCall->arg_end() - 1))->getEndLoc());
+ if (checkArgCount(*this, TheCall, 2))
return true;
- }
-
- if (TheCall->getNumArgs() < 2) {
- return Diag(TheCall->getEndLoc(),
- diag::err_typecheck_call_too_few_args_at_least)
- << 0 /*function call*/ << 2 << TheCall->getNumArgs();
- }
// Type-check the first argument normally.
if (checkBuiltinArgument(*this, TheCall, 0))
@@ -5698,15 +5889,8 @@ bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) {
/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and
/// friends. This is declared to take (...), so we have to check everything.
bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) {
- if (TheCall->getNumArgs() < 2)
- return Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args)
- << 0 << 2 << TheCall->getNumArgs() /*function call*/;
- if (TheCall->getNumArgs() > 2)
- return Diag(TheCall->getArg(2)->getBeginLoc(),
- diag::err_typecheck_call_too_many_args)
- << 0 /*function call*/ << 2 << TheCall->getNumArgs()
- << SourceRange(TheCall->getArg(2)->getBeginLoc(),
- (*(TheCall->arg_end() - 1))->getEndLoc());
+ if (checkArgCount(*this, TheCall, 2))
+ return true;
ExprResult OrigArg0 = TheCall->getArg(0);
ExprResult OrigArg1 = TheCall->getArg(1);
@@ -5744,15 +5928,8 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) {
/// to check everything. We expect the last argument to be a floating point
/// value.
bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
- if (TheCall->getNumArgs() < NumArgs)
- return Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args)
- << 0 << NumArgs << TheCall->getNumArgs() /*function call*/;
- if (TheCall->getNumArgs() > NumArgs)
- return Diag(TheCall->getArg(NumArgs)->getBeginLoc(),
- diag::err_typecheck_call_too_many_args)
- << 0 /*function call*/ << NumArgs << TheCall->getNumArgs()
- << SourceRange(TheCall->getArg(NumArgs)->getBeginLoc(),
- (*(TheCall->arg_end() - 1))->getEndLoc());
+ if (checkArgCount(*this, TheCall, NumArgs))
+ return true;
// __builtin_fpclassify is the only case where NumArgs != 1, so we can count
// on all preceding parameters just being int. Try all of those.
@@ -5792,6 +5969,61 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
return false;
}
+/// Perform semantic analysis for a call to __builtin_complex.
+bool Sema::SemaBuiltinComplex(CallExpr *TheCall) {
+ if (checkArgCount(*this, TheCall, 2))
+ return true;
+
+ bool Dependent = false;
+ for (unsigned I = 0; I != 2; ++I) {
+ Expr *Arg = TheCall->getArg(I);
+ QualType T = Arg->getType();
+ if (T->isDependentType()) {
+ Dependent = true;
+ continue;
+ }
+
+ // Despite supporting _Complex int, GCC requires a real floating point type
+ // for the operands of __builtin_complex.
+ if (!T->isRealFloatingType()) {
+ return Diag(Arg->getBeginLoc(), diag::err_typecheck_call_requires_real_fp)
+ << Arg->getType() << Arg->getSourceRange();
+ }
+
+ ExprResult Converted = DefaultLvalueConversion(Arg);
+ if (Converted.isInvalid())
+ return true;
+ TheCall->setArg(I, Converted.get());
+ }
+
+ if (Dependent) {
+ TheCall->setType(Context.DependentTy);
+ return false;
+ }
+
+ Expr *Real = TheCall->getArg(0);
+ Expr *Imag = TheCall->getArg(1);
+ if (!Context.hasSameType(Real->getType(), Imag->getType())) {
+ return Diag(Real->getBeginLoc(),
+ diag::err_typecheck_call_different_arg_types)
+ << Real->getType() << Imag->getType()
+ << Real->getSourceRange() << Imag->getSourceRange();
+ }
+
+ // We don't allow _Complex _Float16 nor _Complex __fp16 as type specifiers;
+ // don't allow this builtin to form those types either.
+ // FIXME: Should we allow these types?
+ if (Real->getType()->isFloat16Type())
+ return Diag(TheCall->getBeginLoc(), diag::err_invalid_complex_spec)
+ << "_Float16";
+ if (Real->getType()->isHalfType())
+ return Diag(TheCall->getBeginLoc(), diag::err_invalid_complex_spec)
+ << "half";
+
+ TheCall->setType(Context.getComplexType(Real->getType()));
+ return false;
+}
+
// Customized Sema Checking for VSX builtins that have the following signature:
// vector [...] builtinName(vector [...], vector [...], const int);
// Which takes the same type of vectors (any legal vector type) for the first
@@ -5801,21 +6033,11 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
// vector short vec_xxsldwi(vector short, vector short, int);
bool Sema::SemaBuiltinVSX(CallExpr *TheCall) {
unsigned ExpectedNumArgs = 3;
- if (TheCall->getNumArgs() < ExpectedNumArgs)
- return Diag(TheCall->getEndLoc(),
- diag::err_typecheck_call_too_few_args_at_least)
- << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs()
- << TheCall->getSourceRange();
-
- if (TheCall->getNumArgs() > ExpectedNumArgs)
- return Diag(TheCall->getEndLoc(),
- diag::err_typecheck_call_too_many_args_at_most)
- << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs()
- << TheCall->getSourceRange();
+ if (checkArgCount(*this, TheCall, ExpectedNumArgs))
+ return true;
// Check the third argument is a compile time constant
- llvm::APSInt Value;
- if(!TheCall->getArg(2)->isIntegerConstantExpr(Value, Context))
+ if (!TheCall->getArg(2)->isIntegerConstantExpr(Context))
return Diag(TheCall->getBeginLoc(),
diag::err_vsx_builtin_nonconstant_argument)
<< 3 /* argument index */ << TheCall->getDirectCallee()
@@ -5910,17 +6132,18 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
TheCall->getArg(i)->isValueDependent())
continue;
- llvm::APSInt Result(32);
- if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context))
+ Optional<llvm::APSInt> Result;
+ if (!(Result = TheCall->getArg(i)->getIntegerConstantExpr(Context)))
return ExprError(Diag(TheCall->getBeginLoc(),
diag::err_shufflevector_nonconstant_argument)
<< TheCall->getArg(i)->getSourceRange());
// Allow -1 which will be translated to undef in the IR.
- if (Result.isSigned() && Result.isAllOnesValue())
+ if (Result->isSigned() && Result->isAllOnesValue())
continue;
- if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2)
+ if (Result->getActiveBits() > 64 ||
+ Result->getZExtValue() >= numElements * 2)
return ExprError(Diag(TheCall->getBeginLoc(),
diag::err_shufflevector_argument_too_large)
<< TheCall->getArg(i)->getSourceRange());
@@ -6167,10 +6390,11 @@ bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
if (Arg->isTypeDependent() || Arg->isValueDependent()) return false;
- if (!Arg->isIntegerConstantExpr(Result, Context))
+ Optional<llvm::APSInt> R;
+ if (!(R = Arg->getIntegerConstantExpr(Context)))
return Diag(TheCall->getBeginLoc(), diag::err_constant_integer_arg_type)
<< FDecl->getDeclName() << Arg->getSourceRange();
-
+ Result = *R;
return false;
}
@@ -6588,6 +6812,64 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
return false;
}
+/// SemaBuiltinPPCMMACall - Check the call to a PPC MMA builtin for validity.
+/// Emit an error and return true on failure; return false on success.
+/// TypeStr is a string containing the type descriptor of the value returned by
+/// the builtin and the descriptors of the expected type of the arguments.
+bool Sema::SemaBuiltinPPCMMACall(CallExpr *TheCall, const char *TypeStr) {
+
+ assert((TypeStr[0] != '\0') &&
+ "Invalid types in PPC MMA builtin declaration");
+
+ unsigned Mask = 0;
+ unsigned ArgNum = 0;
+
+ // The first type in TypeStr is the type of the value returned by the
+ // builtin. So we first read that type and change the type of TheCall.
+ QualType type = DecodePPCMMATypeFromStr(Context, TypeStr, Mask);
+ TheCall->setType(type);
+
+ while (*TypeStr != '\0') {
+ Mask = 0;
+ QualType ExpectedType = DecodePPCMMATypeFromStr(Context, TypeStr, Mask);
+ if (ArgNum >= TheCall->getNumArgs()) {
+ ArgNum++;
+ break;
+ }
+
+ Expr *Arg = TheCall->getArg(ArgNum);
+ QualType ArgType = Arg->getType();
+
+ if ((ExpectedType->isVoidPointerType() && !ArgType->isPointerType()) ||
+ (!ExpectedType->isVoidPointerType() &&
+ ArgType.getCanonicalType() != ExpectedType))
+ return Diag(Arg->getBeginLoc(), diag::err_typecheck_convert_incompatible)
+ << ArgType << ExpectedType << 1 << 0 << 0;
+
+ // If the value of the Mask is not 0, we have a constraint in the size of
+ // the integer argument so here we ensure the argument is a constant that
+ // is in the valid range.
+ if (Mask != 0 &&
+ SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, Mask, true))
+ return true;
+
+ ArgNum++;
+ }
+
+ // In case we exited early from the previous loop, there are other types to
+ // read from TypeStr. So we need to read them all to ensure we have the right
+ // number of arguments in TheCall and if it is not the case, to display a
+ // better error message.
+ while (*TypeStr != '\0') {
+ (void) DecodePPCMMATypeFromStr(Context, TypeStr, Mask);
+ ArgNum++;
+ }
+ if (checkArgCount(*this, TheCall, ArgNum))
+ return true;
+
+ return false;
+}
+
/// SemaBuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val).
/// This checks that the target supports __builtin_longjmp and
/// that val is a constant 1.
@@ -9966,6 +10248,68 @@ void Sema::CheckStrncatArguments(const CallExpr *CE,
<< FixItHint::CreateReplacement(SR, OS.str());
}
+namespace {
+void CheckFreeArgumentsOnLvalue(Sema &S, const std::string &CalleeName,
+ const UnaryOperator *UnaryExpr,
+ const VarDecl *Var) {
+ StorageClass Class = Var->getStorageClass();
+ if (Class == StorageClass::SC_Extern ||
+ Class == StorageClass::SC_PrivateExtern ||
+ Var->getType()->isReferenceType())
+ return;
+
+ S.Diag(UnaryExpr->getBeginLoc(), diag::warn_free_nonheap_object)
+ << CalleeName << Var;
+}
+
+void CheckFreeArgumentsOnLvalue(Sema &S, const std::string &CalleeName,
+ const UnaryOperator *UnaryExpr, const Decl *D) {
+ if (const auto *Field = dyn_cast<FieldDecl>(D))
+ S.Diag(UnaryExpr->getBeginLoc(), diag::warn_free_nonheap_object)
+ << CalleeName << Field;
+}
+
+void CheckFreeArgumentsAddressof(Sema &S, const std::string &CalleeName,
+ const UnaryOperator *UnaryExpr) {
+ if (UnaryExpr->getOpcode() != UnaryOperator::Opcode::UO_AddrOf)
+ return;
+
+ if (const auto *Lvalue = dyn_cast<DeclRefExpr>(UnaryExpr->getSubExpr()))
+ if (const auto *Var = dyn_cast<VarDecl>(Lvalue->getDecl()))
+ return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, Var);
+
+ if (const auto *Lvalue = dyn_cast<MemberExpr>(UnaryExpr->getSubExpr()))
+ return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr,
+ Lvalue->getMemberDecl());
+}
+
+void CheckFreeArgumentsStackArray(Sema &S, const std::string &CalleeName,
+ const DeclRefExpr *Lvalue) {
+ if (!Lvalue->getType()->isArrayType())
+ return;
+
+ const auto *Var = dyn_cast<VarDecl>(Lvalue->getDecl());
+ if (Var == nullptr)
+ return;
+
+ S.Diag(Lvalue->getBeginLoc(), diag::warn_free_nonheap_object)
+ << CalleeName << Var;
+}
+} // namespace
+
+/// Alerts the user that they are attempting to free a non-malloc'd object.
+void Sema::CheckFreeArguments(const CallExpr *E) {
+ const Expr *Arg = E->getArg(0)->IgnoreParenCasts();
+ const std::string CalleeName =
+ dyn_cast<FunctionDecl>(E->getCalleeDecl())->getQualifiedNameAsString();
+
+ if (const auto *UnaryExpr = dyn_cast<UnaryOperator>(Arg))
+ return CheckFreeArgumentsAddressof(*this, CalleeName, UnaryExpr);
+
+ if (const auto *Lvalue = dyn_cast<DeclRefExpr>(Arg))
+ return CheckFreeArgumentsStackArray(*this, CalleeName, Lvalue);
+}
+
void
Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
SourceLocation ReturnLoc,
@@ -9995,6 +10339,11 @@ Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
<< FD << getLangOpts().CPlusPlus11;
}
}
+
+ // PPC MMA non-pointer types are not allowed as return type. Checking the type
+ // here prevent the user from using a PPC MMA type as trailing return type.
+ if (Context.getTargetInfo().getTriple().isPPC64())
+ CheckPPCMMAType(RetValExp->getType(), ReturnLoc);
}
//===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===//
@@ -10048,15 +10397,23 @@ namespace {
/// Structure recording the 'active' range of an integer-valued
/// expression.
struct IntRange {
- /// The number of bits active in the int.
+ /// The number of bits active in the int. Note that this includes exactly one
+ /// sign bit if !NonNegative.
unsigned Width;
- /// True if the int is known not to have negative values.
+ /// True if the int is known not to have negative values. If so, all leading
+ /// bits before Width are known zero, otherwise they are known to be the
+ /// same as the MSB within Width.
bool NonNegative;
IntRange(unsigned Width, bool NonNegative)
: Width(Width), NonNegative(NonNegative) {}
+ /// Number of bits excluding the sign bit.
+ unsigned valueBits() const {
+ return NonNegative ? Width : Width - 1;
+ }
+
/// Returns the range of the bool type.
static IntRange forBoolType() {
return IntRange(1, true);
@@ -10140,14 +10497,63 @@ struct IntRange {
/// Returns the supremum of two ranges: i.e. their conservative merge.
static IntRange join(IntRange L, IntRange R) {
- return IntRange(std::max(L.Width, R.Width),
+ bool Unsigned = L.NonNegative && R.NonNegative;
+ return IntRange(std::max(L.valueBits(), R.valueBits()) + !Unsigned,
L.NonNegative && R.NonNegative);
}
- /// Returns the infinum of two ranges: i.e. their aggressive merge.
- static IntRange meet(IntRange L, IntRange R) {
- return IntRange(std::min(L.Width, R.Width),
- L.NonNegative || R.NonNegative);
+ /// Return the range of a bitwise-AND of the two ranges.
+ static IntRange bit_and(IntRange L, IntRange R) {
+ unsigned Bits = std::max(L.Width, R.Width);
+ bool NonNegative = false;
+ if (L.NonNegative) {
+ Bits = std::min(Bits, L.Width);
+ NonNegative = true;
+ }
+ if (R.NonNegative) {
+ Bits = std::min(Bits, R.Width);
+ NonNegative = true;
+ }
+ return IntRange(Bits, NonNegative);
+ }
+
+ /// Return the range of a sum of the two ranges.
+ static IntRange sum(IntRange L, IntRange R) {
+ bool Unsigned = L.NonNegative && R.NonNegative;
+ return IntRange(std::max(L.valueBits(), R.valueBits()) + 1 + !Unsigned,
+ Unsigned);
+ }
+
+ /// Return the range of a difference of the two ranges.
+ static IntRange difference(IntRange L, IntRange R) {
+ // We need a 1-bit-wider range if:
+ // 1) LHS can be negative: least value can be reduced.
+ // 2) RHS can be negative: greatest value can be increased.
+ bool CanWiden = !L.NonNegative || !R.NonNegative;
+ bool Unsigned = L.NonNegative && R.Width == 0;
+ return IntRange(std::max(L.valueBits(), R.valueBits()) + CanWiden +
+ !Unsigned,
+ Unsigned);
+ }
+
+ /// Return the range of a product of the two ranges.
+ static IntRange product(IntRange L, IntRange R) {
+ // If both LHS and RHS can be negative, we can form
+ // -2^L * -2^R = 2^(L + R)
+ // which requires L + R + 1 value bits to represent.
+ bool CanWiden = !L.NonNegative && !R.NonNegative;
+ bool Unsigned = L.NonNegative && R.NonNegative;
+ return IntRange(L.valueBits() + R.valueBits() + CanWiden + !Unsigned,
+ Unsigned);
+ }
+
+ /// Return the range of a remainder operation between the two ranges.
+ static IntRange rem(IntRange L, IntRange R) {
+ // The result of a remainder can't be larger than the result of
+ // either side. The sign of the result is the sign of the LHS.
+ bool Unsigned = L.NonNegative;
+ return IntRange(std::min(L.valueBits(), R.valueBits()) + !Unsigned,
+ Unsigned);
}
};
@@ -10205,9 +10611,13 @@ static QualType GetExprType(const Expr *E) {
/// Pseudo-evaluate the given integer expression, estimating the
/// range of values it might take.
///
-/// \param MaxWidth - the width to which the value will be truncated
+/// \param MaxWidth The width to which the value will be truncated.
+/// \param Approximate If \c true, return a likely range for the result: in
+/// particular, assume that aritmetic on narrower types doesn't leave
+/// those types. If \c false, return a range including all possible
+/// result values.
static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth,
- bool InConstantContext) {
+ bool InConstantContext, bool Approximate) {
E = E->IgnoreParens();
// Try a full evaluation first.
@@ -10220,7 +10630,8 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth,
// being of the new, wider type.
if (const auto *CE = dyn_cast<ImplicitCastExpr>(E)) {
if (CE->getCastKind() == CK_NoOp || CE->getCastKind() == CK_LValueToRValue)
- return GetExprRange(C, CE->getSubExpr(), MaxWidth, InConstantContext);
+ return GetExprRange(C, CE->getSubExpr(), MaxWidth, InConstantContext,
+ Approximate);
IntRange OutputTypeRange = IntRange::forValueOfType(C, GetExprType(CE));
@@ -10233,7 +10644,7 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth,
IntRange SubRange = GetExprRange(C, CE->getSubExpr(),
std::min(MaxWidth, OutputTypeRange.Width),
- InConstantContext);
+ InConstantContext, Approximate);
// Bail out if the subexpr's range is as wide as the cast type.
if (SubRange.Width >= OutputTypeRange.Width)
@@ -10251,17 +10662,25 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth,
if (CO->getCond()->EvaluateAsBooleanCondition(CondResult, C))
return GetExprRange(C,
CondResult ? CO->getTrueExpr() : CO->getFalseExpr(),
- MaxWidth, InConstantContext);
+ MaxWidth, InConstantContext, Approximate);
// Otherwise, conservatively merge.
- IntRange L =
- GetExprRange(C, CO->getTrueExpr(), MaxWidth, InConstantContext);
- IntRange R =
- GetExprRange(C, CO->getFalseExpr(), MaxWidth, InConstantContext);
+ // GetExprRange requires an integer expression, but a throw expression
+ // results in a void type.
+ Expr *E = CO->getTrueExpr();
+ IntRange L = E->getType()->isVoidType()
+ ? IntRange{0, true}
+ : GetExprRange(C, E, MaxWidth, InConstantContext, Approximate);
+ E = CO->getFalseExpr();
+ IntRange R = E->getType()->isVoidType()
+ ? IntRange{0, true}
+ : GetExprRange(C, E, MaxWidth, InConstantContext, Approximate);
return IntRange::join(L, R);
}
if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
+ IntRange (*Combine)(IntRange, IntRange) = IntRange::join;
+
switch (BO->getOpcode()) {
case BO_Cmp:
llvm_unreachable("builtin <=> should have class type");
@@ -10293,7 +10712,8 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth,
// been coerced to the LHS type.
case BO_Assign:
// TODO: bitfields?
- return GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext);
+ return GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext,
+ Approximate);
// Operations with opaque sources are black-listed.
case BO_PtrMemD:
@@ -10303,9 +10723,8 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth,
// Bitwise-and uses the *infinum* of the two source ranges.
case BO_And:
case BO_AndAssign:
- return IntRange::meet(
- GetExprRange(C, BO->getLHS(), MaxWidth, InConstantContext),
- GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext));
+ Combine = IntRange::bit_and;
+ break;
// Left shift gets black-listed based on a judgement call.
case BO_Shl:
@@ -10326,18 +10745,20 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth,
// Right shift by a constant can narrow its left argument.
case BO_Shr:
case BO_ShrAssign: {
- IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth, InConstantContext);
+ IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth, InConstantContext,
+ Approximate);
// If the shift amount is a positive constant, drop the width by
// that much.
- llvm::APSInt shift;
- if (BO->getRHS()->isIntegerConstantExpr(shift, C) &&
- shift.isNonNegative()) {
- unsigned zext = shift.getZExtValue();
- if (zext >= L.Width)
- L.Width = (L.NonNegative ? 0 : 1);
- else
- L.Width -= zext;
+ if (Optional<llvm::APSInt> shift =
+ BO->getRHS()->getIntegerConstantExpr(C)) {
+ if (shift->isNonNegative()) {
+ unsigned zext = shift->getZExtValue();
+ if (zext >= L.Width)
+ L.Width = (L.NonNegative ? 0 : 1);
+ else
+ L.Width -= zext;
+ }
}
return L;
@@ -10345,12 +10766,24 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth,
// Comma acts as its right operand.
case BO_Comma:
- return GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext);
+ return GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext,
+ Approximate);
+
+ case BO_Add:
+ if (!Approximate)
+ Combine = IntRange::sum;
+ break;
- // Black-list pointer subtractions.
case BO_Sub:
if (BO->getLHS()->getType()->isPointerType())
return IntRange::forValueOfType(C, GetExprType(E));
+ if (!Approximate)
+ Combine = IntRange::difference;
+ break;
+
+ case BO_Mul:
+ if (!Approximate)
+ Combine = IntRange::product;
break;
// The width of a division result is mostly determined by the size
@@ -10358,12 +10791,13 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth,
case BO_Div: {
// Don't 'pre-truncate' the operands.
unsigned opWidth = C.getIntWidth(GetExprType(E));
- IntRange L = GetExprRange(C, BO->getLHS(), opWidth, InConstantContext);
+ IntRange L = GetExprRange(C, BO->getLHS(), opWidth, InConstantContext,
+ Approximate);
// If the divisor is constant, use that.
- llvm::APSInt divisor;
- if (BO->getRHS()->isIntegerConstantExpr(divisor, C)) {
- unsigned log2 = divisor.logBase2(); // floor(log_2(divisor))
+ if (Optional<llvm::APSInt> divisor =
+ BO->getRHS()->getIntegerConstantExpr(C)) {
+ unsigned log2 = divisor->logBase2(); // floor(log_2(divisor))
if (log2 >= L.Width)
L.Width = (L.NonNegative ? 0 : 1);
else
@@ -10372,36 +10806,35 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth,
}
// Otherwise, just use the LHS's width.
- IntRange R = GetExprRange(C, BO->getRHS(), opWidth, InConstantContext);
+ // FIXME: This is wrong if the LHS could be its minimal value and the RHS
+ // could be -1.
+ IntRange R = GetExprRange(C, BO->getRHS(), opWidth, InConstantContext,
+ Approximate);
return IntRange(L.Width, L.NonNegative && R.NonNegative);
}
- // The result of a remainder can't be larger than the result of
- // either side.
- case BO_Rem: {
- // Don't 'pre-truncate' the operands.
- unsigned opWidth = C.getIntWidth(GetExprType(E));
- IntRange L = GetExprRange(C, BO->getLHS(), opWidth, InConstantContext);
- IntRange R = GetExprRange(C, BO->getRHS(), opWidth, InConstantContext);
-
- IntRange meet = IntRange::meet(L, R);
- meet.Width = std::min(meet.Width, MaxWidth);
- return meet;
- }
+ case BO_Rem:
+ Combine = IntRange::rem;
+ break;
// The default behavior is okay for these.
- case BO_Mul:
- case BO_Add:
case BO_Xor:
case BO_Or:
break;
}
- // The default case is to treat the operation as if it were closed
- // on the narrowest type that encompasses both operands.
- IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth, InConstantContext);
- IntRange R = GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext);
- return IntRange::join(L, R);
+ // Combine the two ranges, but limit the result to the type in which we
+ // performed the computation.
+ QualType T = GetExprType(E);
+ unsigned opWidth = C.getIntWidth(T);
+ IntRange L =
+ GetExprRange(C, BO->getLHS(), opWidth, InConstantContext, Approximate);
+ IntRange R =
+ GetExprRange(C, BO->getRHS(), opWidth, InConstantContext, Approximate);
+ IntRange C = Combine(L, R);
+ C.NonNegative |= T->isUnsignedIntegerOrEnumerationType();
+ C.Width = std::min(C.Width, MaxWidth);
+ return C;
}
if (const auto *UO = dyn_cast<UnaryOperator>(E)) {
@@ -10416,12 +10849,14 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth,
return IntRange::forValueOfType(C, GetExprType(E));
default:
- return GetExprRange(C, UO->getSubExpr(), MaxWidth, InConstantContext);
+ return GetExprRange(C, UO->getSubExpr(), MaxWidth, InConstantContext,
+ Approximate);
}
}
if (const auto *OVE = dyn_cast<OpaqueValueExpr>(E))
- return GetExprRange(C, OVE->getSourceExpr(), MaxWidth, InConstantContext);
+ return GetExprRange(C, OVE->getSourceExpr(), MaxWidth, InConstantContext,
+ Approximate);
if (const auto *BitField = E->getSourceBitField())
return IntRange(BitField->getBitWidthValue(C),
@@ -10431,8 +10866,9 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth,
}
static IntRange GetExprRange(ASTContext &C, const Expr *E,
- bool InConstantContext) {
- return GetExprRange(C, E, C.getIntWidth(GetExprType(E)), InConstantContext);
+ bool InConstantContext, bool Approximate) {
+ return GetExprRange(C, E, C.getIntWidth(GetExprType(E)), InConstantContext,
+ Approximate);
}
/// Checks whether the given value, which currently has the given
@@ -10677,15 +11113,16 @@ static bool CheckTautologicalComparison(Sema &S, BinaryOperator *E,
S.Context.hasSameUnqualifiedType(Constant->getType(), Other->getType()))
return false;
- // TODO: Investigate using GetExprRange() to get tighter bounds
- // on the bit ranges.
+ IntRange OtherValueRange = GetExprRange(
+ S.Context, Other, S.isConstantEvaluated(), /*Approximate*/ false);
+
QualType OtherT = Other->getType();
if (const auto *AT = OtherT->getAs<AtomicType>())
OtherT = AT->getValueType();
- IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT);
+ IntRange OtherTypeRange = IntRange::forValueOfType(S.Context, OtherT);
// Special case for ObjC BOOL on targets where its a typedef for a signed char
- // (Namely, macOS).
+ // (Namely, macOS). FIXME: IntRange::forValueOfType should do this.
bool IsObjCSignedCharBool = S.getLangOpts().ObjC &&
S.NSAPIObj->isObjCBOOLType(OtherT) &&
OtherT->isSpecificBuiltinType(BuiltinType::SChar);
@@ -10695,17 +11132,37 @@ static bool CheckTautologicalComparison(Sema &S, BinaryOperator *E,
bool OtherIsBooleanDespiteType =
!OtherT->isBooleanType() && Other->isKnownToHaveBooleanValue();
if (OtherIsBooleanDespiteType || IsObjCSignedCharBool)
- OtherRange = IntRange::forBoolType();
+ OtherTypeRange = OtherValueRange = IntRange::forBoolType();
- // Determine the promoted range of the other type and see if a comparison of
- // the constant against that range is tautological.
- PromotedRange OtherPromotedRange(OtherRange, Value.getBitWidth(),
- Value.isUnsigned());
- auto Cmp = OtherPromotedRange.compare(Value);
+ // Check if all values in the range of possible values of this expression
+ // lead to the same comparison outcome.
+ PromotedRange OtherPromotedValueRange(OtherValueRange, Value.getBitWidth(),
+ Value.isUnsigned());
+ auto Cmp = OtherPromotedValueRange.compare(Value);
auto Result = PromotedRange::constantValue(E->getOpcode(), Cmp, RhsConstant);
if (!Result)
return false;
+ // Also consider the range determined by the type alone. This allows us to
+ // classify the warning under the proper diagnostic group.
+ bool TautologicalTypeCompare = false;
+ {
+ PromotedRange OtherPromotedTypeRange(OtherTypeRange, Value.getBitWidth(),
+ Value.isUnsigned());
+ auto TypeCmp = OtherPromotedTypeRange.compare(Value);
+ if (auto TypeResult = PromotedRange::constantValue(E->getOpcode(), TypeCmp,
+ RhsConstant)) {
+ TautologicalTypeCompare = true;
+ Cmp = TypeCmp;
+ Result = TypeResult;
+ }
+ }
+
+ // Don't warn if the non-constant operand actually always evaluates to the
+ // same value.
+ if (!TautologicalTypeCompare && OtherValueRange.Width == 0)
+ return false;
+
// Suppress the diagnostic for an in-range comparison if the constant comes
// from a macro or enumerator. We don't want to diagnose
//
@@ -10716,6 +11173,12 @@ static bool CheckTautologicalComparison(Sema &S, BinaryOperator *E,
if (InRange && IsEnumConstOrFromMacro(S, Constant))
return false;
+ // A comparison of an unsigned bit-field against 0 is really a type problem,
+ // even though at the type level the bit-field might promote to 'signed int'.
+ if (Other->refersToBitField() && InRange && Value == 0 &&
+ Other->getType()->isUnsignedIntegerOrEnumerationType())
+ TautologicalTypeCompare = true;
+
// If this is a comparison to an enum constant, include that
// constant in the diagnostic.
const EnumConstantDecl *ED = nullptr;
@@ -10734,6 +11197,14 @@ static bool CheckTautologicalComparison(Sema &S, BinaryOperator *E,
OS << Value;
}
+ if (!TautologicalTypeCompare) {
+ S.Diag(E->getOperatorLoc(), diag::warn_tautological_compare_value_range)
+ << RhsConstant << OtherValueRange.Width << OtherValueRange.NonNegative
+ << E->getOpcodeStr() << OS.str() << *Result
+ << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+ return true;
+ }
+
if (IsObjCSignedCharBool) {
S.DiagRuntimeBehavior(E->getOperatorLoc(), E,
S.PDiag(diag::warn_tautological_compare_objc_bool)
@@ -10795,23 +11266,20 @@ static void AnalyzeComparison(Sema &S, BinaryOperator *E) {
Expr *RHS = E->getRHS();
if (T->isIntegralType(S.Context)) {
- llvm::APSInt RHSValue;
- llvm::APSInt LHSValue;
-
- bool IsRHSIntegralLiteral = RHS->isIntegerConstantExpr(RHSValue, S.Context);
- bool IsLHSIntegralLiteral = LHS->isIntegerConstantExpr(LHSValue, S.Context);
+ Optional<llvm::APSInt> RHSValue = RHS->getIntegerConstantExpr(S.Context);
+ Optional<llvm::APSInt> LHSValue = LHS->getIntegerConstantExpr(S.Context);
// We don't care about expressions whose result is a constant.
- if (IsRHSIntegralLiteral && IsLHSIntegralLiteral)
+ if (RHSValue && LHSValue)
return AnalyzeImpConvsInComparison(S, E);
// We only care about expressions where just one side is literal
- if (IsRHSIntegralLiteral ^ IsLHSIntegralLiteral) {
+ if ((bool)RHSValue ^ (bool)LHSValue) {
// Is the constant on the RHS or LHS?
- const bool RhsConstant = IsRHSIntegralLiteral;
+ const bool RhsConstant = (bool)RHSValue;
Expr *Const = RhsConstant ? RHS : LHS;
Expr *Other = RhsConstant ? LHS : RHS;
- const llvm::APSInt &Value = RhsConstant ? RHSValue : LHSValue;
+ const llvm::APSInt &Value = RhsConstant ? *RHSValue : *LHSValue;
// Check whether an integer constant comparison results in a value
// of 'true' or 'false'.
@@ -10856,8 +11324,8 @@ static void AnalyzeComparison(Sema &S, BinaryOperator *E) {
}
// Otherwise, calculate the effective range of the signed operand.
- IntRange signedRange =
- GetExprRange(S.Context, signedOperand, S.isConstantEvaluated());
+ IntRange signedRange = GetExprRange(
+ S.Context, signedOperand, S.isConstantEvaluated(), /*Approximate*/ true);
// Go ahead and analyze implicit conversions in the operands. Note
// that we skip the implicit conversions on both sides.
@@ -10875,7 +11343,8 @@ static void AnalyzeComparison(Sema &S, BinaryOperator *E) {
if (E->isEqualityOp()) {
unsigned comparisonWidth = S.Context.getIntWidth(T);
IntRange unsignedRange =
- GetExprRange(S.Context, unsignedOperand, S.isConstantEvaluated());
+ GetExprRange(S.Context, unsignedOperand, S.isConstantEvaluated(),
+ /*Approximate*/ true);
// We should never be unable to prove that the unsigned operand is
// non-negative.
@@ -10915,7 +11384,7 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
BitfieldEnumDecl->getNumPositiveBits() > 0 &&
BitfieldEnumDecl->getNumNegativeBits() == 0) {
S.Diag(InitLoc, diag::warn_no_underlying_type_specified_for_enum_bitfield)
- << BitfieldEnumDecl->getNameAsString();
+ << BitfieldEnumDecl;
}
}
@@ -11695,9 +12164,9 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
Expr::EvalResult Result;
if (E->EvaluateAsFixedPoint(Result, S.Context, Expr::SE_AllowSideEffects,
S.isConstantEvaluated())) {
- APFixedPoint Value = Result.Val.getFixedPoint();
- APFixedPoint MaxVal = S.Context.getFixedPointMax(T);
- APFixedPoint MinVal = S.Context.getFixedPointMin(T);
+ llvm::APFixedPoint Value = Result.Val.getFixedPoint();
+ llvm::APFixedPoint MaxVal = S.Context.getFixedPointMax(T);
+ llvm::APFixedPoint MinVal = S.Context.getFixedPointMin(T);
if (Value > MaxVal || Value < MinVal) {
S.DiagRuntimeBehavior(E->getExprLoc(), E,
S.PDiag(diag::warn_impcast_fixed_point_range)
@@ -11712,7 +12181,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
if (!S.isConstantEvaluated() &&
E->EvaluateAsFixedPoint(Result, S.Context,
Expr::SE_AllowSideEffects)) {
- APFixedPoint FXResult = Result.Val.getFixedPoint();
+ llvm::APFixedPoint FXResult = Result.Val.getFixedPoint();
bool Overflowed;
llvm::APSInt IntResult = FXResult.convertToInt(
@@ -11737,7 +12206,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
llvm::APSInt Value = Result.Val.getInt();
bool Overflowed;
- APFixedPoint IntResult = APFixedPoint::getFromIntValue(
+ llvm::APFixedPoint IntResult = llvm::APFixedPoint::getFromIntValue(
Value, S.Context.getFixedPointSemantics(T), &Overflowed);
if (Overflowed) {
@@ -11758,7 +12227,8 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
if (SourceBT && TargetBT && SourceBT->isIntegerType() &&
TargetBT->isFloatingType() && !IsListInit) {
// Determine the number of precision bits in the source integer type.
- IntRange SourceRange = GetExprRange(S.Context, E, S.isConstantEvaluated());
+ IntRange SourceRange = GetExprRange(S.Context, E, S.isConstantEvaluated(),
+ /*Approximate*/ true);
unsigned int SourcePrecision = SourceRange.Width;
// Determine the number of precision bits in the
@@ -11769,8 +12239,8 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
if (SourcePrecision > 0 && TargetPrecision > 0 &&
SourcePrecision > TargetPrecision) {
- llvm::APSInt SourceInt;
- if (E->isIntegerConstantExpr(SourceInt, S.Context)) {
+ if (Optional<llvm::APSInt> SourceInt =
+ E->getIntegerConstantExpr(S.Context)) {
// If the source integer is a constant, convert it to the target
// floating point type. Issue a warning if the value changes
// during the whole conversion.
@@ -11778,11 +12248,11 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
S.Context.getFloatTypeSemantics(QualType(TargetBT, 0)));
llvm::APFloat::opStatus ConversionStatus =
TargetFloatValue.convertFromAPInt(
- SourceInt, SourceBT->isSignedInteger(),
+ *SourceInt, SourceBT->isSignedInteger(),
llvm::APFloat::rmNearestTiesToEven);
if (ConversionStatus != llvm::APFloat::opOK) {
- std::string PrettySourceValue = SourceInt.toString(10);
+ std::string PrettySourceValue = SourceInt->toString(10);
SmallString<32> PrettyTargetValue;
TargetFloatValue.toString(PrettyTargetValue, TargetPrecision);
@@ -11823,10 +12293,13 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
<< E->getType());
}
- IntRange SourceRange = GetExprRange(S.Context, E, S.isConstantEvaluated());
+ IntRange SourceTypeRange =
+ IntRange::forTargetOfCanonicalType(S.Context, Source);
+ IntRange LikelySourceRange =
+ GetExprRange(S.Context, E, S.isConstantEvaluated(), /*Approximate*/ true);
IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, Target);
- if (SourceRange.Width > TargetRange.Width) {
+ if (LikelySourceRange.Width > TargetRange.Width) {
// If the source is a constant, use a default-on diagnostic.
// TODO: this should happen for bitfield stores, too.
Expr::EvalResult Result;
@@ -11845,7 +12318,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
E->getExprLoc(), E,
S.PDiag(diag::warn_impcast_integer_precision_constant)
<< PrettySourceValue << PrettyTargetValue << E->getType() << T
- << E->getSourceRange() << clang::SourceRange(CC));
+ << E->getSourceRange() << SourceRange(CC));
return;
}
@@ -11859,7 +12332,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_precision);
}
- if (TargetRange.Width > SourceRange.Width) {
+ if (TargetRange.Width > SourceTypeRange.Width) {
if (auto *UO = dyn_cast<UnaryOperator>(E))
if (UO->getOpcode() == UO_Minus)
if (Source->isUnsignedIntegerType()) {
@@ -11872,8 +12345,9 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
}
}
- if (TargetRange.Width == SourceRange.Width && !TargetRange.NonNegative &&
- SourceRange.NonNegative && Source->isSignedIntegerType()) {
+ if (TargetRange.Width == LikelySourceRange.Width &&
+ !TargetRange.NonNegative && LikelySourceRange.NonNegative &&
+ Source->isSignedIntegerType()) {
// Warn when doing a signed to signed conversion, warn if the positive
// source value is exactly the width of the target type, which will
// cause a negative value to be stored.
@@ -11890,7 +12364,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
E->getExprLoc(), E,
S.PDiag(diag::warn_impcast_integer_precision_constant)
<< PrettySourceValue << PrettyTargetValue << E->getType() << T
- << E->getSourceRange() << clang::SourceRange(CC));
+ << E->getSourceRange() << SourceRange(CC));
return;
}
}
@@ -11898,9 +12372,9 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
// Fall through for non-constants to give a sign conversion warning.
}
- if ((TargetRange.NonNegative && !SourceRange.NonNegative) ||
- (!TargetRange.NonNegative && SourceRange.NonNegative &&
- SourceRange.Width == TargetRange.Width)) {
+ if ((TargetRange.NonNegative && !LikelySourceRange.NonNegative) ||
+ (!TargetRange.NonNegative && LikelySourceRange.NonNegative &&
+ LikelySourceRange.Width == TargetRange.Width)) {
if (S.SourceMgr.isInSystemMacro(CC))
return;
@@ -13505,10 +13979,9 @@ getAlignmentAndOffsetFromBinAddOrSub(const Expr *PtrE, const Expr *IntE,
if (!P)
return llvm::None;
- llvm::APSInt IdxRes;
CharUnits EltSize = Ctx.getTypeSizeInChars(PointeeType);
- if (IntE->isIntegerConstantExpr(IdxRes, Ctx)) {
- CharUnits Offset = EltSize * IdxRes.getExtValue();
+ if (Optional<llvm::APSInt> IdxRes = IntE->getIntegerConstantExpr(Ctx)) {
+ CharUnits Offset = EltSize * IdxRes->getExtValue();
if (IsSub)
Offset = -Offset;
return std::make_pair(P->first, P->second + Offset);
@@ -13911,8 +14384,7 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
if (ND)
DiagRuntimeBehavior(ND->getBeginLoc(), BaseExpr,
- PDiag(diag::note_array_declared_here)
- << ND->getDeclName());
+ PDiag(diag::note_array_declared_here) << ND);
}
void Sema::CheckArrayAccess(const Expr *expr) {
@@ -14133,9 +14605,10 @@ namespace {
return;
if (Expr *RHS = BinOp->getRHS()) {
RHS = RHS->IgnoreParenCasts();
- llvm::APSInt Value;
+ Optional<llvm::APSInt> Value;
VarWillBeReased =
- (RHS && RHS->isIntegerConstantExpr(Value, Context) && Value == 0);
+ (RHS && (Value = RHS->getIntegerConstantExpr(Context)) &&
+ *Value == 0);
}
}
}
@@ -15362,14 +15835,15 @@ ExprResult Sema::SemaBuiltinMatrixTranspose(CallExpr *TheCall,
// Get and verify the matrix dimensions.
static llvm::Optional<unsigned>
getAndVerifyMatrixDimension(Expr *Expr, StringRef Name, Sema &S) {
- llvm::APSInt Value(64);
SourceLocation ErrorPos;
- if (!Expr->isIntegerConstantExpr(Value, S.Context, &ErrorPos)) {
+ Optional<llvm::APSInt> Value =
+ Expr->getIntegerConstantExpr(S.Context, &ErrorPos);
+ if (!Value) {
S.Diag(Expr->getBeginLoc(), diag::err_builtin_matrix_scalar_unsigned_arg)
<< Name;
return {};
}
- uint64_t Dim = Value.getZExtValue();
+ uint64_t Dim = Value->getZExtValue();
if (!ConstantMatrixType::isDimensionValid(Dim)) {
S.Diag(Expr->getBeginLoc(), diag::err_builtin_matrix_invalid_dimension)
<< Name << ConstantMatrixType::getMaxElementsPerDimension();
@@ -15473,13 +15947,15 @@ ExprResult Sema::SemaBuiltinMatrixColumnMajorLoad(CallExpr *TheCall,
StrideExpr = StrideConv.get();
TheCall->setArg(3, StrideExpr);
- llvm::APSInt Value(64);
- if (MaybeRows && StrideExpr->isIntegerConstantExpr(Value, Context)) {
- uint64_t Stride = Value.getZExtValue();
- if (Stride < *MaybeRows) {
- Diag(StrideExpr->getBeginLoc(),
- diag::err_builtin_matrix_stride_too_small);
- ArgError = true;
+ if (MaybeRows) {
+ if (Optional<llvm::APSInt> Value =
+ StrideExpr->getIntegerConstantExpr(Context)) {
+ uint64_t Stride = Value->getZExtValue();
+ if (Stride < *MaybeRows) {
+ Diag(StrideExpr->getBeginLoc(),
+ diag::err_builtin_matrix_stride_too_small);
+ ArgError = true;
+ }
}
}
@@ -15570,13 +16046,15 @@ ExprResult Sema::SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall,
}
// Check stride argument.
- llvm::APSInt Value(64);
- if (MatrixTy && StrideExpr->isIntegerConstantExpr(Value, Context)) {
- uint64_t Stride = Value.getZExtValue();
- if (Stride < MatrixTy->getNumRows()) {
- Diag(StrideExpr->getBeginLoc(),
- diag::err_builtin_matrix_stride_too_small);
- ArgError = true;
+ if (MatrixTy) {
+ if (Optional<llvm::APSInt> Value =
+ StrideExpr->getIntegerConstantExpr(Context)) {
+ uint64_t Stride = Value->getZExtValue();
+ if (Stride < MatrixTy->getNumRows()) {
+ Diag(StrideExpr->getBeginLoc(),
+ diag::err_builtin_matrix_stride_too_small);
+ ArgError = true;
+ }
}
}
@@ -15585,3 +16063,38 @@ ExprResult Sema::SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall,
return CallResult;
}
+
+/// \brief Enforce the bounds of a TCB
+/// CheckTCBEnforcement - Enforces that every function in a named TCB only
+/// directly calls other functions in the same TCB as marked by the enforce_tcb
+/// and enforce_tcb_leaf attributes.
+void Sema::CheckTCBEnforcement(const CallExpr *TheCall,
+ const FunctionDecl *Callee) {
+ const FunctionDecl *Caller = getCurFunctionDecl();
+
+ // Calls to builtins are not enforced.
+ if (!Caller || !Caller->hasAttr<EnforceTCBAttr>() ||
+ Callee->getBuiltinID() != 0)
+ return;
+
+ // Search through the enforce_tcb and enforce_tcb_leaf attributes to find
+ // all TCBs the callee is a part of.
+ llvm::StringSet<> CalleeTCBs;
+ for_each(Callee->specific_attrs<EnforceTCBAttr>(),
+ [&](const auto *A) { CalleeTCBs.insert(A->getTCBName()); });
+ for_each(Callee->specific_attrs<EnforceTCBLeafAttr>(),
+ [&](const auto *A) { CalleeTCBs.insert(A->getTCBName()); });
+
+ // Go through the TCBs the caller is a part of and emit warnings if Caller
+ // is in a TCB that the Callee is not.
+ for_each(
+ Caller->specific_attrs<EnforceTCBAttr>(),
+ [&](const auto *A) {
+ StringRef CallerTCB = A->getTCBName();
+ if (CalleeTCBs.count(CallerTCB) == 0) {
+ this->Diag(TheCall->getExprLoc(),
+ diag::warn_tcb_enforcement_violation) << Callee
+ << CallerTCB;
+ }
+ });
+}
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 0a8a27068ebf..c2785fd60fc2 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -2294,6 +2294,29 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S,
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
+
+ if (SemaRef.getLangOpts().CPlusPlus11 || SemaRef.getLangOpts().ObjC) {
+ // for ( range_declaration (:|in) range_expression ) { statements }
+ Builder.AddTypedTextChunk("for");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("range-declaration");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ if (SemaRef.getLangOpts().ObjC)
+ Builder.AddTextChunk("in");
+ else
+ Builder.AddChunk(CodeCompletionString::CK_Colon);
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("range-expression");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+ Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+ Builder.AddPlaceholderChunk("statements");
+ Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+ Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+ Results.AddResult(Result(Builder.TakeString()));
+ }
}
if (S->getContinueParent()) {
@@ -2700,6 +2723,10 @@ static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
case NullabilityKind::Unspecified:
Result += "null_unspecified ";
break;
+
+ case NullabilityKind::NullableResult:
+ llvm_unreachable("Not supported as a context-sensitive keyword!");
+ break;
}
}
}
@@ -3502,9 +3529,11 @@ CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
Result.AddTypedTextChunk("");
}
unsigned Idx = 0;
+ // The extra Idx < Sel.getNumArgs() check is needed due to legacy C-style
+ // method parameters.
for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
PEnd = Method->param_end();
- P != PEnd; (void)++P, ++Idx) {
+ P != PEnd && Idx < Sel.getNumArgs(); (void)++P, ++Idx) {
if (Idx > 0) {
std::string Keyword;
if (Idx > StartParameter)
@@ -4256,7 +4285,7 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
DS.getTypeSpecType() == DeclSpec::TST_typename &&
DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
- DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
+ DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified &&
!DS.isTypeAltiVecVector() && S &&
(S->getFlags() & Scope::DeclScope) != 0 &&
(S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
@@ -5395,8 +5424,8 @@ void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
AddTypeQualifierResults(DS, Results, LangOpts);
if (LangOpts.CPlusPlus11) {
Results.AddResult("noexcept");
- if (D.getContext() == DeclaratorContext::MemberContext &&
- !D.isCtorOrDtor() && !D.isStaticMember()) {
+ if (D.getContext() == DeclaratorContext::Member && !D.isCtorOrDtor() &&
+ !D.isStaticMember()) {
if (!VS || !VS->isFinalSpecified())
Results.AddResult("final");
if (!VS || !VS->isOverrideSpecified())
@@ -5500,7 +5529,7 @@ typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
static void mergeCandidatesWithResults(
Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results,
- OverloadCandidateSet &CandidateSet, SourceLocation Loc) {
+ OverloadCandidateSet &CandidateSet, SourceLocation Loc, size_t ArgSize) {
// Sort the overload candidate set by placing the best overloads first.
llvm::stable_sort(CandidateSet, [&](const OverloadCandidate &X,
const OverloadCandidate &Y) {
@@ -5510,8 +5539,19 @@ static void mergeCandidatesWithResults(
// Add the remaining viable overload candidates as code-completion results.
for (OverloadCandidate &Candidate : CandidateSet) {
- if (Candidate.Function && Candidate.Function->isDeleted())
- continue;
+ if (Candidate.Function) {
+ if (Candidate.Function->isDeleted())
+ continue;
+ if (!Candidate.Function->isVariadic() &&
+ Candidate.Function->getNumParams() <= ArgSize &&
+ // Having zero args is annoying, normally we don't surface a function
+ // with 2 params, if you already have 2 params, because you are
+ // inserting the 3rd now. But with zero, it helps the user to figure
+ // out there are no overloads that take any arguments. Hence we are
+ // keeping the overload.
+ ArgSize > 0)
+ continue;
+ }
if (Candidate.Viable)
Results.push_back(ResultCandidate(Candidate.Function));
}
@@ -5562,22 +5602,25 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
// FIXME: Provide support for variadic template functions.
// Ignore type-dependent call expressions entirely.
- if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
- Expr::hasAnyTypeDependentArguments(Args)) {
+ if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args))
return QualType();
- }
+ // In presence of dependent args we surface all possible signatures using the
+ // non-dependent args in the prefix. Afterwards we do a post filtering to make
+ // sure provided candidates satisfy parameter count restrictions.
+ auto ArgsWithoutDependentTypes =
+ Args.take_while([](Expr *Arg) { return !Arg->isTypeDependent(); });
+
+ SmallVector<ResultCandidate, 8> Results;
+ Expr *NakedFn = Fn->IgnoreParenCasts();
// Build an overload candidate set based on the functions we find.
SourceLocation Loc = Fn->getExprLoc();
OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
- SmallVector<ResultCandidate, 8> Results;
-
- Expr *NakedFn = Fn->IgnoreParenCasts();
- if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
- AddOverloadedCallCandidates(ULE, Args, CandidateSet,
+ if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) {
+ AddOverloadedCallCandidates(ULE, ArgsWithoutDependentTypes, CandidateSet,
/*PartialOverloading=*/true);
- else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
+ } else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
if (UME->hasExplicitTemplateArgs()) {
UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
@@ -5587,7 +5630,8 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
// Add the base as first argument (use a nullptr if the base is implicit).
SmallVector<Expr *, 12> ArgExprs(
1, UME->isImplicitAccess() ? nullptr : UME->getBase());
- ArgExprs.append(Args.begin(), Args.end());
+ ArgExprs.append(ArgsWithoutDependentTypes.begin(),
+ ArgsWithoutDependentTypes.end());
UnresolvedSet<8> Decls;
Decls.append(UME->decls_begin(), UME->decls_end());
const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
@@ -5606,7 +5650,7 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
Results.push_back(ResultCandidate(FD));
else
AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
- Args, CandidateSet,
+ ArgsWithoutDependentTypes, CandidateSet,
/*SuppressUserConversions=*/false,
/*PartialOverloading=*/true);
@@ -5621,7 +5665,8 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
LookupQualifiedName(R, DC);
R.suppressDiagnostics();
SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
- ArgExprs.append(Args.begin(), Args.end());
+ ArgExprs.append(ArgsWithoutDependentTypes.begin(),
+ ArgsWithoutDependentTypes.end());
AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
/*ExplicitArgs=*/nullptr,
/*SuppressUserConversions=*/false,
@@ -5635,7 +5680,8 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
T = T->getPointeeType();
if (auto FP = T->getAs<FunctionProtoType>()) {
- if (!TooManyArguments(FP->getNumParams(), Args.size(),
+ if (!TooManyArguments(FP->getNumParams(),
+ ArgsWithoutDependentTypes.size(),
/*PartialOverloading=*/true) ||
FP->isVariadic())
Results.push_back(ResultCandidate(FP));
@@ -5644,7 +5690,7 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
Results.push_back(ResultCandidate(FT));
}
}
- mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
+ mergeCandidatesWithResults(*this, Results, CandidateSet, Loc, Args.size());
QualType ParamType =
ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
return !CandidateSet.empty() ? ParamType : QualType();
@@ -5685,7 +5731,7 @@ QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
}
SmallVector<ResultCandidate, 8> Results;
- mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
+ mergeCandidatesWithResults(*this, Results, CandidateSet, Loc, Args.size());
return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
}
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index ddd95faebe99..1ff7b1cdd515 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -1053,25 +1053,20 @@ ReturnTypeRequirement(TemplateParameterList *TPL) :
auto *Constraint =
cast_or_null<ConceptSpecializationExpr>(
TC->getImmediatelyDeclaredConstraint());
- bool Dependent = false;
- if (Constraint->getTemplateArgsAsWritten()) {
- for (auto &ArgLoc :
- Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1)) {
- if (ArgLoc.getArgument().isDependent()) {
- Dependent = true;
- break;
- }
- }
- }
+ bool Dependent =
+ Constraint->getTemplateArgsAsWritten() &&
+ TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
+ Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
TypeConstraintInfo.setInt(Dependent ? 1 : 0);
}
concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
- Requirement(RK_Type, T->getType()->isDependentType(),
+ Requirement(RK_Type, T->getType()->isInstantiationDependentType(),
T->getType()->containsUnexpandedParameterPack(),
// We reach this ctor with either dependent types (in which
// IsSatisfied doesn't matter) or with non-dependent type in
// which the existence of the type indicates satisfaction.
- /*IsSatisfied=*/true
- ), Value(T),
- Status(T->getType()->isDependentType() ? SS_Dependent : SS_Satisfied) {}
+ /*IsSatisfied=*/true),
+ Value(T),
+ Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
+ : SS_Satisfied) {}
diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index 992cccac6405..7a48bfa429e9 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -398,39 +398,54 @@ static Expr *maybeTailCall(Sema &S, QualType RetType, Expr *E,
diag::warn_coroutine_handle_address_invalid_return_type)
<< JustAddress->getType();
+ // Clean up temporary objects so that they don't live across suspension points
+ // unnecessarily. We choose to clean up before the call to
+ // __builtin_coro_resume so that the cleanup code are not inserted in-between
+ // the resume call and return instruction, which would interfere with the
+ // musttail call contract.
+ JustAddress = S.MaybeCreateExprWithCleanups(JustAddress);
return buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_resume,
JustAddress);
}
/// Build calls to await_ready, await_suspend, and await_resume for a co_await
/// expression.
+/// The generated AST tries to clean up temporary objects as early as
+/// possible so that they don't live across suspension points if possible.
+/// Having temporary objects living across suspension points unnecessarily can
+/// lead to large frame size, and also lead to memory corruptions if the
+/// coroutine frame is destroyed after coming back from suspension. This is done
+/// by wrapping both the await_ready call and the await_suspend call with
+/// ExprWithCleanups. In the end of this function, we also need to explicitly
+/// set cleanup state so that the CoawaitExpr is also wrapped with an
+/// ExprWithCleanups to clean up the awaiter associated with the co_await
+/// expression.
static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise,
SourceLocation Loc, Expr *E) {
OpaqueValueExpr *Operand = new (S.Context)
OpaqueValueExpr(Loc, E->getType(), VK_LValue, E->getObjectKind(), E);
- // Assume invalid until we see otherwise.
- ReadySuspendResumeResult Calls = {{}, Operand, /*IsInvalid=*/true};
-
- ExprResult CoroHandleRes = buildCoroutineHandle(S, CoroPromise->getType(), Loc);
- if (CoroHandleRes.isInvalid())
- return Calls;
- Expr *CoroHandle = CoroHandleRes.get();
+ // Assume valid until we see otherwise.
+ // Further operations are responsible for setting IsInalid to true.
+ ReadySuspendResumeResult Calls = {{}, Operand, /*IsInvalid=*/false};
- const StringRef Funcs[] = {"await_ready", "await_suspend", "await_resume"};
- MultiExprArg Args[] = {None, CoroHandle, None};
- for (size_t I = 0, N = llvm::array_lengthof(Funcs); I != N; ++I) {
- ExprResult Result = buildMemberCall(S, Operand, Loc, Funcs[I], Args[I]);
- if (Result.isInvalid())
- return Calls;
- Calls.Results[I] = Result.get();
- }
+ using ACT = ReadySuspendResumeResult::AwaitCallType;
- // Assume the calls are valid; all further checking should make them invalid.
- Calls.IsInvalid = false;
+ auto BuildSubExpr = [&](ACT CallType, StringRef Func,
+ MultiExprArg Arg) -> Expr * {
+ ExprResult Result = buildMemberCall(S, Operand, Loc, Func, Arg);
+ if (Result.isInvalid()) {
+ Calls.IsInvalid = true;
+ return nullptr;
+ }
+ Calls.Results[CallType] = Result.get();
+ return Result.get();
+ };
- using ACT = ReadySuspendResumeResult::AwaitCallType;
- CallExpr *AwaitReady = cast<CallExpr>(Calls.Results[ACT::ACT_Ready]);
+ CallExpr *AwaitReady =
+ cast_or_null<CallExpr>(BuildSubExpr(ACT::ACT_Ready, "await_ready", None));
+ if (!AwaitReady)
+ return Calls;
if (!AwaitReady->getType()->isDependentType()) {
// [expr.await]p3 [...]
// — await-ready is the expression e.await_ready(), contextually converted
@@ -442,18 +457,36 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise,
S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
<< AwaitReady->getDirectCallee() << E->getSourceRange();
Calls.IsInvalid = true;
- }
- Calls.Results[ACT::ACT_Ready] = Conv.get();
+ } else
+ Calls.Results[ACT::ACT_Ready] = S.MaybeCreateExprWithCleanups(Conv.get());
+ }
+
+ ExprResult CoroHandleRes =
+ buildCoroutineHandle(S, CoroPromise->getType(), Loc);
+ if (CoroHandleRes.isInvalid()) {
+ Calls.IsInvalid = true;
+ return Calls;
}
- CallExpr *AwaitSuspend = cast<CallExpr>(Calls.Results[ACT::ACT_Suspend]);
+ Expr *CoroHandle = CoroHandleRes.get();
+ CallExpr *AwaitSuspend = cast_or_null<CallExpr>(
+ BuildSubExpr(ACT::ACT_Suspend, "await_suspend", CoroHandle));
+ if (!AwaitSuspend)
+ return Calls;
if (!AwaitSuspend->getType()->isDependentType()) {
// [expr.await]p3 [...]
// - await-suspend is the expression e.await_suspend(h), which shall be
- // a prvalue of type void or bool.
+ // a prvalue of type void, bool, or std::coroutine_handle<Z> for some
+ // type Z.
QualType RetType = AwaitSuspend->getCallReturnType(S.Context);
// Experimental support for coroutine_handle returning await_suspend.
- if (Expr *TailCallSuspend = maybeTailCall(S, RetType, AwaitSuspend, Loc))
+ if (Expr *TailCallSuspend =
+ maybeTailCall(S, RetType, AwaitSuspend, Loc))
+ // Note that we don't wrap the expression with ExprWithCleanups here
+ // because that might interfere with tailcall contract (e.g. inserting
+ // clean up instructions in-between tailcall and return). Instead
+ // ExprWithCleanups is wrapped within maybeTailCall() prior to the resume
+ // call.
Calls.Results[ACT::ACT_Suspend] = TailCallSuspend;
else {
// non-class prvalues always have cv-unqualified types
@@ -465,10 +498,17 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise,
S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
<< AwaitSuspend->getDirectCallee();
Calls.IsInvalid = true;
- }
+ } else
+ Calls.Results[ACT::ACT_Suspend] =
+ S.MaybeCreateExprWithCleanups(AwaitSuspend);
}
}
+ BuildSubExpr(ACT::ACT_Resume, "await_resume", None);
+
+ // Make sure the awaiter object gets a chance to be cleaned up.
+ S.Cleanup.setExprNeedsCleanups(true);
+
return Calls;
}
@@ -504,6 +544,7 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
auto *VD = VarDecl::Create(Context, FD, FD->getLocation(), FD->getLocation(),
&PP.getIdentifierTable().get("__promise"), T,
Context.getTrivialTypeSourceInfo(T, Loc), SC_None);
+ VD->setImplicit();
CheckVariableDeclarationType(VD);
if (VD->isInvalidDecl())
return nullptr;
@@ -865,8 +906,8 @@ ExprResult Sema::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr *E,
SourceLocation CallLoc = E->getExprLoc();
// Build the await_ready, await_suspend, await_resume calls.
- ReadySuspendResumeResult RSS =
- buildCoawaitCalls(*this, Coroutine->CoroutinePromise, CallLoc, E);
+ ReadySuspendResumeResult RSS = buildCoawaitCalls(
+ *this, Coroutine->CoroutinePromise, CallLoc, E);
if (RSS.IsInvalid)
return ExprError();
@@ -920,8 +961,8 @@ ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
// Build the await_ready, await_suspend, await_resume calls.
- ReadySuspendResumeResult RSS =
- buildCoawaitCalls(*this, Coroutine->CoroutinePromise, Loc, E);
+ ReadySuspendResumeResult RSS = buildCoawaitCalls(
+ *this, Coroutine->CoroutinePromise, Loc, E);
if (RSS.IsInvalid)
return ExprError();
@@ -1537,6 +1578,7 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
S.Context, &FD, FD.getLocation(), FD.getLocation(),
&S.PP.getIdentifierTable().get("__coro_gro"), GroType,
S.Context.getTrivialTypeSourceInfo(GroType, Loc), SC_None);
+ GroDecl->setImplicit();
S.CheckVariableDeclarationType(GroDecl);
if (GroDecl->isInvalidDecl())
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 3e2b61ae8cdf..3ee0c43097d7 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -255,7 +255,7 @@ static ParsedType recoverFromTypeInKnownDependentBase(Sema &S,
// We found some types in dependent base classes. Recover as if the user
// wrote 'typename MyClass::II' instead of 'II'. We'll fully resolve the
// lookup during template instantiation.
- S.Diag(NameLoc, diag::ext_found_via_dependent_bases_lookup) << &II;
+ S.Diag(NameLoc, diag::ext_found_in_dependent_base) << &II;
ASTContext &Context = S.Context;
auto *NNS = NestedNameSpecifier::Create(Context, nullptr, false,
@@ -436,9 +436,7 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
Res != ResEnd; ++Res) {
if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res) ||
(AllowDeducedTemplate && getAsTypeTemplateDecl(*Res))) {
- if (!IIDecl ||
- (*Res)->getLocation().getRawEncoding() <
- IIDecl->getLocation().getRawEncoding())
+ if (!IIDecl || (*Res)->getLocation() < IIDecl->getLocation())
IIDecl = *Res;
}
}
@@ -1184,23 +1182,20 @@ Corrected:
return ParsedType::make(T);
}
- // FIXME: This is context-dependent. We need to defer building the member
- // expression until the classification is consumed.
- if (FirstDecl->isCXXClassMember())
- return NameClassification::ContextIndependentExpr(
- BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result, nullptr,
- S));
-
// If we already know which single declaration is referenced, just annotate
- // that declaration directly.
+ // that declaration directly. Defer resolving even non-overloaded class
+ // member accesses, as we need to defer certain access checks until we know
+ // the context.
bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren));
- if (Result.isSingleResult() && !ADL)
+ if (Result.isSingleResult() && !ADL && !FirstDecl->isCXXClassMember())
return NameClassification::NonType(Result.getRepresentativeDecl());
- // Build an UnresolvedLookupExpr. Note that this doesn't depend on the
- // context in which we performed classification, so it's safe to do now.
- return NameClassification::ContextIndependentExpr(
- BuildDeclarationNameExpr(SS, Result, ADL));
+ // Otherwise, this is an overload set that we will need to resolve later.
+ Result.suppressDiagnostics();
+ return NameClassification::OverloadSet(UnresolvedLookupExpr::Create(
+ Context, Result.getNamingClass(), SS.getWithLocInContext(Context),
+ Result.getLookupNameInfo(), ADL, Result.isOverloadedResult(),
+ Result.begin(), Result.end()));
}
ExprResult
@@ -1240,6 +1235,30 @@ ExprResult Sema::ActOnNameClassifiedAsNonType(Scope *S, const CXXScopeSpec &SS,
return BuildDeclarationNameExpr(SS, Result, ADL);
}
+ExprResult Sema::ActOnNameClassifiedAsOverloadSet(Scope *S, Expr *E) {
+ // For an implicit class member access, transform the result into a member
+ // access expression if necessary.
+ auto *ULE = cast<UnresolvedLookupExpr>(E);
+ if ((*ULE->decls_begin())->isCXXClassMember()) {
+ CXXScopeSpec SS;
+ SS.Adopt(ULE->getQualifierLoc());
+
+ // Reconstruct the lookup result.
+ LookupResult Result(*this, ULE->getName(), ULE->getNameLoc(),
+ LookupOrdinaryName);
+ Result.setNamingClass(ULE->getNamingClass());
+ for (auto I = ULE->decls_begin(), E = ULE->decls_end(); I != E; ++I)
+ Result.addDecl(*I, I.getAccess());
+ Result.resolveKind();
+ return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result,
+ nullptr, S);
+ }
+
+ // Otherwise, this is already in the form we needed, and no further checks
+ // are necessary.
+ return ULE;
+}
+
Sema::TemplateNameKindForDiagnostics
Sema::getTemplateNameKindForDiagnostics(TemplateName Name) {
auto *TD = Name.getAsTemplateDecl();
@@ -1457,10 +1476,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
// Out-of-line definitions shouldn't be pushed into scope in C++, unless they
// are function-local declarations.
- if (getLangOpts().CPlusPlus && D->isOutOfLine() &&
- !D->getDeclContext()->getRedeclContext()->Equals(
- D->getLexicalDeclContext()->getRedeclContext()) &&
- !D->getLexicalDeclContext()->isFunctionOrMethod())
+ if (getLangOpts().CPlusPlus && D->isOutOfLine() && !S->getFnParent())
return;
// Template instantiations should also not be pushed into scope.
@@ -1742,25 +1758,20 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
if (D->isInvalidDecl())
return false;
- bool Referenced = false;
if (auto *DD = dyn_cast<DecompositionDecl>(D)) {
// For a decomposition declaration, warn if none of the bindings are
// referenced, instead of if the variable itself is referenced (which
// it is, by the bindings' expressions).
- for (auto *BD : DD->bindings()) {
- if (BD->isReferenced()) {
- Referenced = true;
- break;
- }
- }
+ for (auto *BD : DD->bindings())
+ if (BD->isReferenced())
+ return false;
} else if (!D->getDeclName()) {
return false;
} else if (D->isReferenced() || D->isUsed()) {
- Referenced = true;
+ return false;
}
- if (Referenced || D->hasAttr<UnusedAttr>() ||
- D->hasAttr<ObjCPreciseLifetimeAttr>())
+ if (D->hasAttr<UnusedAttr>() || D->hasAttr<ObjCPreciseLifetimeAttr>())
return false;
if (isa<LabelDecl>(D))
@@ -1905,7 +1916,7 @@ static void CheckPoppedLabel(LabelDecl *L, Sema &S) {
else
Diagnose = L->getStmt() == nullptr;
if (Diagnose)
- S.Diag(L->getLocation(), diag::err_undeclared_label_use) <<L->getDeclName();
+ S.Diag(L->getLocation(), diag::err_undeclared_label_use) << L;
}
void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
@@ -2019,24 +2030,6 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) {
return S;
}
-/// Looks up the declaration of "struct objc_super" and
-/// saves it for later use in building builtin declaration of
-/// objc_msgSendSuper and objc_msgSendSuper_stret. If no such
-/// pre-existing declaration exists no action takes place.
-static void LookupPredefedObjCSuperType(Sema &ThisSema, Scope *S,
- IdentifierInfo *II) {
- if (!II->isStr("objc_msgSendSuper"))
- return;
- ASTContext &Context = ThisSema.Context;
-
- LookupResult Result(ThisSema, &Context.Idents.get("objc_super"),
- SourceLocation(), Sema::LookupTagName);
- ThisSema.LookupName(Result, S);
- if (Result.getResultKind() == LookupResult::Found)
- if (const TagDecl *TD = Result.getAsSingle<TagDecl>())
- Context.setObjCSuperType(Context.getTagDeclType(TD));
-}
-
static StringRef getHeaderName(Builtin::Context &BuiltinInfo, unsigned ID,
ASTContext::GetBuiltinTypeError Error) {
switch (Error) {
@@ -2054,6 +2047,42 @@ static StringRef getHeaderName(Builtin::Context &BuiltinInfo, unsigned ID,
llvm_unreachable("unhandled error kind");
}
+FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, QualType Type,
+ unsigned ID, SourceLocation Loc) {
+ DeclContext *Parent = Context.getTranslationUnitDecl();
+
+ if (getLangOpts().CPlusPlus) {
+ LinkageSpecDecl *CLinkageDecl = LinkageSpecDecl::Create(
+ Context, Parent, Loc, Loc, LinkageSpecDecl::lang_c, false);
+ CLinkageDecl->setImplicit();
+ Parent->addDecl(CLinkageDecl);
+ Parent = CLinkageDecl;
+ }
+
+ FunctionDecl *New = FunctionDecl::Create(Context, Parent, Loc, Loc, II, Type,
+ /*TInfo=*/nullptr, SC_Extern, false,
+ Type->isFunctionProtoType());
+ New->setImplicit();
+ New->addAttr(BuiltinAttr::CreateImplicit(Context, ID));
+
+ // Create Decl objects for each parameter, adding them to the
+ // FunctionDecl.
+ if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(Type)) {
+ SmallVector<ParmVarDecl *, 16> Params;
+ for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
+ ParmVarDecl *parm = ParmVarDecl::Create(
+ Context, New, SourceLocation(), SourceLocation(), nullptr,
+ FT->getParamType(i), /*TInfo=*/nullptr, SC_None, nullptr);
+ parm->setScopeInfo(0, i);
+ Params.push_back(parm);
+ }
+ New->setParams(Params);
+ }
+
+ AddKnownFunctionAttributes(New);
+ return New;
+}
+
/// LazilyCreateBuiltin - The specified Builtin-ID was first used at
/// file scope. lazily create a decl for it. ForRedeclaration is true
/// if we're creating this built-in in anticipation of redeclaring the
@@ -2061,7 +2090,7 @@ static StringRef getHeaderName(Builtin::Context &BuiltinInfo, unsigned ID,
NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
Scope *S, bool ForRedeclaration,
SourceLocation Loc) {
- LookupPredefedObjCSuperType(*this, S, II);
+ LookupNecessaryTypesForBuiltin(S, ID);
ASTContext::GetBuiltinTypeError Error;
QualType R = Context.GetBuiltinType(ID, Error);
@@ -2071,7 +2100,8 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
// If we have a builtin without an associated type we should not emit a
// warning when we were not able to find a type for it.
- if (Error == ASTContext::GE_Missing_type)
+ if (Error == ASTContext::GE_Missing_type ||
+ Context.BuiltinInfo.allowTypeMismatch(ID))
return nullptr;
// If we could not find a type for setjmp it is because the jmp_buf type was
@@ -2095,50 +2125,15 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
Context.BuiltinInfo.isHeaderDependentFunction(ID))) {
Diag(Loc, diag::ext_implicit_lib_function_decl)
<< Context.BuiltinInfo.getName(ID) << R;
- if (Context.BuiltinInfo.getHeaderName(ID) &&
- !Diags.isIgnored(diag::ext_implicit_lib_function_decl, Loc))
+ if (const char *Header = Context.BuiltinInfo.getHeaderName(ID))
Diag(Loc, diag::note_include_header_or_declare)
- << Context.BuiltinInfo.getHeaderName(ID)
- << Context.BuiltinInfo.getName(ID);
+ << Header << Context.BuiltinInfo.getName(ID);
}
if (R.isNull())
return nullptr;
- DeclContext *Parent = Context.getTranslationUnitDecl();
- if (getLangOpts().CPlusPlus) {
- LinkageSpecDecl *CLinkageDecl =
- LinkageSpecDecl::Create(Context, Parent, Loc, Loc,
- LinkageSpecDecl::lang_c, false);
- CLinkageDecl->setImplicit();
- Parent->addDecl(CLinkageDecl);
- Parent = CLinkageDecl;
- }
-
- FunctionDecl *New = FunctionDecl::Create(Context,
- Parent,
- Loc, Loc, II, R, /*TInfo=*/nullptr,
- SC_Extern,
- false,
- R->isFunctionProtoType());
- New->setImplicit();
-
- // Create Decl objects for each parameter, adding them to the
- // FunctionDecl.
- if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(R)) {
- SmallVector<ParmVarDecl*, 16> Params;
- for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
- ParmVarDecl *parm =
- ParmVarDecl::Create(Context, New, SourceLocation(), SourceLocation(),
- nullptr, FT->getParamType(i), /*TInfo=*/nullptr,
- SC_None, nullptr);
- parm->setScopeInfo(0, i);
- Params.push_back(parm);
- }
- New->setParams(Params);
- }
-
- AddKnownFunctionAttributes(New);
+ FunctionDecl *New = CreateBuiltin(II, R, ID, Loc);
RegisterLocallyScopedExternCDecl(New, S);
// TUScope is the translation-unit scope to insert this function into.
@@ -2146,7 +2141,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
// relate Scopes to DeclContexts, and probably eliminate CurContext
// entirely, but we're not there yet.
DeclContext *SavedContext = CurContext;
- CurContext = Parent;
+ CurContext = New->getDeclContext();
PushOnScopeChains(New, TUScope);
CurContext = SavedContext;
return New;
@@ -2591,6 +2586,8 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
return false;
} else if (const auto *MA = dyn_cast<MinSizeAttr>(Attr))
NewAttr = S.mergeMinSizeAttr(D, *MA);
+ else if (const auto *SNA = dyn_cast<SwiftNameAttr>(Attr))
+ NewAttr = S.mergeSwiftNameAttr(D, *SNA, SNA->getName());
else if (const auto *OA = dyn_cast<OptimizeNoneAttr>(Attr))
NewAttr = S.mergeOptimizeNoneAttr(D, *OA);
else if (const auto *InternalLinkageA = dyn_cast<InternalLinkageAttr>(Attr))
@@ -2615,6 +2612,10 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
NewAttr = S.mergeImportModuleAttr(D, *IMA);
else if (const auto *INA = dyn_cast<WebAssemblyImportNameAttr>(Attr))
NewAttr = S.mergeImportNameAttr(D, *INA);
+ else if (const auto *TCBA = dyn_cast<EnforceTCBAttr>(Attr))
+ NewAttr = S.mergeEnforceTCBAttr(D, *TCBA);
+ else if (const auto *TCBLA = dyn_cast<EnforceTCBLeafAttr>(Attr))
+ NewAttr = S.mergeEnforceTCBLeafAttr(D, *TCBLA);
else if (Attr->shouldInheritEvenIfAlreadyPresent() || !DeclHasAttr(D, Attr))
NewAttr = cast<InheritableAttr>(Attr->clone(S.Context));
@@ -2638,8 +2639,11 @@ static const NamedDecl *getDefinition(const Decl *D) {
return Def;
return VD->getActingDefinition();
}
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- return FD->getDefinition();
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ const FunctionDecl *Def = nullptr;
+ if (FD->isDefined(Def, true))
+ return Def;
+ }
return nullptr;
}
@@ -3234,6 +3238,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
}
}
+ // If the old declaration was found in an inline namespace and the new
+ // declaration was qualified, update the DeclContext to match.
+ adjustDeclContextForDeclaratorDecl(New, Old);
+
// If the old declaration is invalid, just give up here.
if (Old->isInvalidDecl())
return true;
@@ -3348,7 +3356,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
// there but not here.
NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
RequiresAdjustment = true;
- } else if (New->getBuiltinID()) {
+ } else if (Old->getBuiltinID()) {
+ // Builtin attribute isn't propagated to the new one yet at this point,
+ // so we check if the old one is a builtin.
+
// Calling Conventions on a Builtin aren't really useful and setting a
// default calling convention and cdecl'ing some builtin redeclarations is
// common, so warn and ignore the calling convention on the redeclaration.
@@ -3781,18 +3792,6 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
Diag(New->getLocation(), diag::warn_redecl_library_builtin) << New;
Diag(OldLocation, diag::note_previous_builtin_declaration)
<< Old << Old->getType();
-
- // If this is a global redeclaration, just forget hereafter
- // about the "builtin-ness" of the function.
- //
- // Doing this for local extern declarations is problematic. If
- // the builtin declaration remains visible, a second invalid
- // local declaration will produce a hard error; if it doesn't
- // remain visible, a single bogus local redeclaration (which is
- // actually only a warning) could break all the downstream code.
- if (!New->getLexicalDeclContext()->isFunctionOrMethod())
- New->getIdentifier()->revertBuiltin();
-
return false;
}
@@ -4057,6 +4056,10 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
return New->setInvalidDecl();
}
+ // If the old declaration was found in an inline namespace and the new
+ // declaration was qualified, update the DeclContext to match.
+ adjustDeclContextForDeclaratorDecl(New, Old);
+
// Ensure the template parameters are compatible.
if (NewTemplate &&
!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
@@ -4241,7 +4244,6 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
New->setPreviousDecl(Old);
if (NewTemplate)
NewTemplate->setPreviousDecl(OldTemplate);
- adjustDeclContextForDeclaratorDecl(New, Old);
// Inherit access appropriately.
New->setAccess(Old->getAccess());
@@ -4606,10 +4608,10 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
if (Tag)
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_tag)
<< GetDiagnosticTypeSpecifierID(DS.getTypeSpecType())
- << DS.getConstexprSpecifier();
+ << static_cast<int>(DS.getConstexprSpecifier());
else
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_wrong_decl_kind)
- << DS.getConstexprSpecifier();
+ << static_cast<int>(DS.getConstexprSpecifier());
// Don't emit warnings after this error.
return TagD;
}
@@ -4745,7 +4747,10 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
if (!DeclaresAnything) {
// In C, we allow this as a (popular) extension / bug. Don't bother
// producing further diagnostics for redundant qualifiers after this.
- Diag(DS.getBeginLoc(), diag::ext_no_declarators) << DS.getSourceRange();
+ Diag(DS.getBeginLoc(), (IsExplicitInstantiation || !TemplateParams.empty())
+ ? diag::err_no_declarators
+ : diag::ext_no_declarators)
+ << DS.getSourceRange();
return TagD;
}
@@ -5164,7 +5169,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
Diag(DS.getBeginLoc(), diag::ext_no_declarators) << DS.getSourceRange();
// Mock up a declarator.
- Declarator Dc(DS, DeclaratorContext::MemberContext);
+ Declarator Dc(DS, DeclaratorContext::Member);
TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
assert(TInfo && "couldn't build declarator info for anonymous struct/union");
@@ -5261,7 +5266,7 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
assert(Record && "expected a record!");
// Mock up a declarator.
- Declarator Dc(DS, DeclaratorContext::TypeNameContext);
+ Declarator Dc(DS, DeclaratorContext::TypeName);
TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
assert(TInfo && "couldn't build declarator info for anonymous struct");
@@ -5346,8 +5351,8 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
case UnqualifiedIdKind::IK_OperatorFunctionId:
NameInfo.setName(Context.DeclarationNames.getCXXOperatorName(
Name.OperatorFunctionId.Operator));
- NameInfo.getInfo().CXXOperatorName.BeginOpNameLoc
- = Name.OperatorFunctionId.SymbolLocations[0];
+ NameInfo.getInfo().CXXOperatorName.BeginOpNameLoc =
+ Name.OperatorFunctionId.SymbolLocations[0].getRawEncoding();
NameInfo.getInfo().CXXOperatorName.EndOpNameLoc
= Name.EndLocation.getRawEncoding();
return NameInfo;
@@ -5495,7 +5500,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
// Grab the type from the parser.
TypeSourceInfo *TSI = nullptr;
QualType T = S.GetTypeFromParser(DS.getRepAsType(), &TSI);
- if (T.isNull() || !T->isDependentType()) break;
+ if (T.isNull() || !T->isInstantiationDependentType()) break;
// Make sure there's a type source info. This isn't really much
// of a waste; most dependent types should have type source info
@@ -5547,7 +5552,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
}
Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) {
- D.setFunctionDefinitionKind(FDK_Declaration);
+ D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
Decl *Dcl = HandleDeclarator(S, D, MultiTemplateParamsArg());
if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer() &&
@@ -5936,9 +5941,14 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T);
if (!VLATy)
return QualType();
- // FIXME: We should probably handle this case
- if (VLATy->getElementType()->isVariablyModifiedType())
- return QualType();
+
+ QualType ElemTy = VLATy->getElementType();
+ if (ElemTy->isVariablyModifiedType()) {
+ ElemTy = TryToFixInvalidVariablyModifiedType(ElemTy, Context,
+ SizeIsNegative, Oversized);
+ if (ElemTy.isNull())
+ return QualType();
+ }
Expr::EvalResult Result;
if (!VLATy->getSizeExpr() ||
@@ -5954,16 +5964,19 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
}
// Check whether the array is too large to be addressed.
- unsigned ActiveSizeBits
- = ConstantArrayType::getNumAddressingBits(Context, VLATy->getElementType(),
- Res);
+ unsigned ActiveSizeBits =
+ (!ElemTy->isDependentType() && !ElemTy->isVariablyModifiedType() &&
+ !ElemTy->isIncompleteType() && !ElemTy->isUndeducedType())
+ ? ConstantArrayType::getNumAddressingBits(Context, ElemTy, Res)
+ : Res.getActiveBits();
if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
Oversized = Res;
return QualType();
}
- return Context.getConstantArrayType(
- VLATy->getElementType(), Res, VLATy->getSizeExpr(), ArrayType::Normal, 0);
+ QualType FoldedArrayType = Context.getConstantArrayType(
+ ElemTy, Res, VLATy->getSizeExpr(), ArrayType::Normal, 0);
+ return Qs.apply(Context, FoldedArrayType);
}
static void
@@ -5989,7 +6002,13 @@ FixInvalidVariablyModifiedTypeLoc(TypeLoc SrcTL, TypeLoc DstTL) {
ArrayTypeLoc DstATL = DstTL.castAs<ArrayTypeLoc>();
TypeLoc SrcElemTL = SrcATL.getElementLoc();
TypeLoc DstElemTL = DstATL.getElementLoc();
- DstElemTL.initializeFullCopy(SrcElemTL);
+ if (VariableArrayTypeLoc SrcElemATL =
+ SrcElemTL.getAs<VariableArrayTypeLoc>()) {
+ ConstantArrayTypeLoc DstElemATL = DstElemTL.castAs<ConstantArrayTypeLoc>();
+ FixInvalidVariablyModifiedTypeLoc(SrcElemATL, DstElemATL);
+ } else {
+ DstElemTL.initializeFullCopy(SrcElemTL);
+ }
DstATL.setLBracketLoc(SrcATL.getLBracketLoc());
DstATL.setSizeExpr(SrcATL.getSizeExpr());
DstATL.setRBracketLoc(SrcATL.getRBracketLoc());
@@ -6014,6 +6033,31 @@ TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo,
return FixedTInfo;
}
+/// Attempt to fold a variable-sized type to a constant-sized type, returning
+/// true if we were successful.
+static bool tryToFixVariablyModifiedVarType(Sema &S, TypeSourceInfo *&TInfo,
+ QualType &T, SourceLocation Loc,
+ unsigned FailedFoldDiagID) {
+ bool SizeIsNegative;
+ llvm::APSInt Oversized;
+ TypeSourceInfo *FixedTInfo = TryToFixInvalidVariablyModifiedTypeSourceInfo(
+ TInfo, S.Context, SizeIsNegative, Oversized);
+ if (FixedTInfo) {
+ S.Diag(Loc, diag::ext_vla_folded_to_constant);
+ TInfo = FixedTInfo;
+ T = FixedTInfo->getType();
+ return true;
+ }
+
+ if (SizeIsNegative)
+ S.Diag(Loc, diag::err_typecheck_negative_array_size);
+ else if (Oversized.getBoolValue())
+ S.Diag(Loc, diag::err_array_too_large) << Oversized.toString(10);
+ else if (FailedFoldDiagID)
+ S.Diag(Loc, FailedFoldDiagID);
+ return false;
+}
+
/// Register the given locally-scoped extern "C" declaration so
/// that it can be found later for redeclarations. We include any extern "C"
/// declaration that is not visible in the translation unit here, not just
@@ -6073,7 +6117,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
<< getLangOpts().CPlusPlus17;
if (D.getDeclSpec().hasConstexprSpecifier())
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
- << 1 << D.getDeclSpec().getConstexprSpecifier();
+ << 1 << static_cast<int>(D.getDeclSpec().getConstexprSpecifier());
if (D.getName().Kind != UnqualifiedIdKind::IK_Identifier) {
if (D.getName().Kind == UnqualifiedIdKind::IK_DeductionGuideName)
@@ -6119,7 +6163,7 @@ Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) {
SizeIsNegative,
Oversized);
if (FixedTInfo) {
- Diag(NewTD->getLocation(), diag::warn_illegal_constant_array_size);
+ Diag(NewTD->getLocation(), diag::ext_vla_folded_to_constant);
NewTD->setTypeSourceInfo(FixedTInfo);
} else {
if (SizeIsNegative)
@@ -6501,7 +6545,7 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
// special MSVC extension: in the last case, the declaration is treated as if
// it were marked dllexport.
bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false;
- bool IsMicrosoft = S.Context.getTargetInfo().getCXXABI().isMicrosoft();
+ bool IsMicrosoftABI = S.Context.getTargetInfo().shouldDLLImportComdatSymbols();
if (const auto *VD = dyn_cast<VarDecl>(NewDecl)) {
// Ignore static data because out-of-line definitions are diagnosed
// separately.
@@ -6515,9 +6559,9 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
}
if (OldImportAttr && !HasNewAttr &&
- (!IsInline || (IsMicrosoft && IsTemplate)) && !IsStaticDataMember &&
+ (!IsInline || (IsMicrosoftABI && IsTemplate)) && !IsStaticDataMember &&
!NewDecl->isLocalExternDecl() && !IsQualifiedFriend) {
- if (IsMicrosoft && IsDefinition) {
+ if (IsMicrosoftABI && IsDefinition) {
S.Diag(NewDecl->getLocation(),
diag::warn_redeclaration_without_import_attribute)
<< NewDecl;
@@ -6534,7 +6578,7 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
OldDecl->dropAttr<DLLImportAttr>();
NewDecl->dropAttr<DLLImportAttr>();
}
- } else if (IsInline && OldImportAttr && !IsMicrosoft) {
+ } else if (IsInline && OldImportAttr && !IsMicrosoftABI) {
// In MinGW, seeing a function declared inline drops the dllimport
// attribute.
OldDecl->dropAttr<DLLImportAttr>();
@@ -6713,14 +6757,16 @@ static bool diagnoseOpenCLTypes(Scope *S, Sema &Se, Declarator &D,
}
// OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed.
- QualType NR = R;
- while (NR->isPointerType()) {
- if (NR->isFunctionPointerType()) {
- Se.Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer);
- D.setInvalidType();
- return false;
+ if (!Se.getOpenCLOptions().isEnabled("__cl_clang_function_pointers")) {
+ QualType NR = R;
+ while (NR->isPointerType() || NR->isMemberFunctionPointerType()) {
+ if (NR->isFunctionPointerType() || NR->isMemberFunctionPointerType()) {
+ Se.Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer);
+ D.setInvalidType();
+ return false;
+ }
+ NR = NR->getPointeeType();
}
- NR = NR->getPointeeType();
}
if (!Se.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
@@ -6852,6 +6898,12 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
+ // If this variable has a variable-modified type and an initializer, try to
+ // fold to a constant-sized type. This is otherwise invalid.
+ if (D.hasInitializer() && R->isVariablyModifiedType())
+ tryToFixVariablyModifiedVarType(*this, TInfo, R, D.getIdentifierLoc(),
+ /*DiagID=*/0);
+
bool IsMemberSpecialization = false;
bool IsVariableTemplateSpecialization = false;
bool IsPartialSpecialization = false;
@@ -6970,19 +7022,18 @@ NamedDecl *Sema::ActOnVariableDeclarator(
TemplateParams->getRAngleLoc());
TemplateParams = nullptr;
} else {
+ // Check that we can declare a template here.
+ if (CheckTemplateDeclScope(S, TemplateParams))
+ return nullptr;
+
if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
// This is an explicit specialization or a partial specialization.
- // FIXME: Check that we can declare a specialization here.
IsVariableTemplateSpecialization = true;
IsPartialSpecialization = TemplateParams->size() > 0;
} else { // if (TemplateParams->size() > 0)
// This is a template declaration.
IsVariableTemplate = true;
- // Check that we can declare a template here.
- if (CheckTemplateDeclScope(S, TemplateParams))
- return nullptr;
-
// Only C++1y supports variable templates (N3651).
Diag(D.getIdentifierLoc(),
getLangOpts().CPlusPlus14
@@ -6991,6 +7042,10 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
} else {
+ // Check that we can declare a member specialization here.
+ if (!TemplateParamLists.empty() && IsMemberSpecialization &&
+ CheckTemplateDeclScope(S, TemplateParamLists.back()))
+ return nullptr;
assert((Invalid ||
D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) &&
"should have a 'template<>' for this decl");
@@ -7110,16 +7165,16 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
switch (D.getDeclSpec().getConstexprSpecifier()) {
- case CSK_unspecified:
+ case ConstexprSpecKind::Unspecified:
break;
- case CSK_consteval:
+ case ConstexprSpecKind::Consteval:
Diag(D.getDeclSpec().getConstexprSpecLoc(),
- diag::err_constexpr_wrong_decl_kind)
- << D.getDeclSpec().getConstexprSpecifier();
+ diag::err_constexpr_wrong_decl_kind)
+ << static_cast<int>(D.getDeclSpec().getConstexprSpecifier());
LLVM_FALLTHROUGH;
- case CSK_constexpr:
+ case ConstexprSpecKind::Constexpr:
NewVD->setConstexpr(true);
MaybeAddCUDAConstantAttr(NewVD);
// C++1z [dcl.spec.constexpr]p1:
@@ -7131,7 +7186,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
NewVD->setImplicitlyInline();
break;
- case CSK_constinit:
+ case ConstexprSpecKind::Constinit:
if (!NewVD->hasGlobalStorage())
Diag(D.getDeclSpec().getConstexprSpecLoc(),
diag::err_constinit_local_variable);
@@ -7173,9 +7228,10 @@ NamedDecl *Sema::ActOnVariableDeclarator(
<< FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
else if (NewVD->hasLocalStorage())
Diag(NewVD->getLocation(), diag::err_module_private_local)
- << 0 << NewVD->getDeclName()
- << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
- << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
+ << 0 << NewVD
+ << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
+ << FixItHint::CreateRemoval(
+ D.getDeclSpec().getModulePrivateSpecLoc());
else {
NewVD->setModulePrivate();
if (NewTemplate)
@@ -7982,7 +8038,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
return;
}
- Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size);
+ Diag(NewVD->getLocation(), diag::ext_vla_folded_to_constant);
NewVD->setType(FixedT);
NewVD->setTypeSourceInfo(FixedTInfo);
}
@@ -8022,6 +8078,14 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
NewVD->setInvalidDecl();
return;
}
+
+ // PPC MMA non-pointer types are not allowed as non-local variable types.
+ if (Context.getTargetInfo().getTriple().isPPC64() &&
+ !NewVD->isLocalVarDecl() &&
+ CheckPPCMMAType(T, NewVD->getLocation())) {
+ NewVD->setInvalidDecl();
+ return;
+ }
}
/// Perform semantic checking on a newly-created variable
@@ -8056,73 +8120,54 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) {
return false;
}
-namespace {
-struct FindOverriddenMethod {
- Sema *S;
- CXXMethodDecl *Method;
-
- /// Member lookup function that determines whether a given C++
- /// method overrides a method in a base class, to be used with
- /// CXXRecordDecl::lookupInBases().
- bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
- RecordDecl *BaseRecord =
- Specifier->getType()->castAs<RecordType>()->getDecl();
+/// 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) {
+ llvm::SmallPtrSet<const CXXMethodDecl*, 4> Overridden;
- DeclarationName Name = Method->getDeclName();
+ // Look for methods in base classes that this method might override.
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/false,
+ /*DetectVirtual=*/false);
+ auto VisitBase = [&] (const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
+ CXXRecordDecl *BaseRecord = Specifier->getType()->getAsCXXRecordDecl();
+ DeclarationName Name = MD->getDeclName();
- // FIXME: Do we care about other names here too?
if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
// We really want to find the base class destructor here.
- QualType T = S->Context.getTypeDeclType(BaseRecord);
- CanQualType CT = S->Context.getCanonicalType(T);
-
- Name = S->Context.DeclarationNames.getCXXDestructorName(CT);
- }
-
- for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty();
- Path.Decls = Path.Decls.slice(1)) {
- NamedDecl *D = Path.Decls.front();
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
- if (MD->isVirtual() &&
- !S->IsOverload(
- Method, MD, /*UseMemberUsingDeclRules=*/false,
- /*ConsiderCudaAttrs=*/true,
- // C++2a [class.virtual]p2 does not consider requires clauses
- // when overriding.
- /*ConsiderRequiresClauses=*/false))
- return true;
+ QualType T = Context.getTypeDeclType(BaseRecord);
+ CanQualType CT = Context.getCanonicalType(T);
+ Name = Context.DeclarationNames.getCXXDestructorName(CT);
+ }
+
+ for (NamedDecl *BaseND : BaseRecord->lookup(Name)) {
+ CXXMethodDecl *BaseMD =
+ dyn_cast<CXXMethodDecl>(BaseND->getCanonicalDecl());
+ if (!BaseMD || !BaseMD->isVirtual() ||
+ IsOverload(MD, BaseMD, /*UseMemberUsingDeclRules=*/false,
+ /*ConsiderCudaAttrs=*/true,
+ // C++2a [class.virtual]p2 does not consider requires
+ // clauses when overriding.
+ /*ConsiderRequiresClauses=*/false))
+ continue;
+
+ if (Overridden.insert(BaseMD).second) {
+ MD->addOverriddenMethod(BaseMD);
+ CheckOverridingFunctionReturnType(MD, BaseMD);
+ CheckOverridingFunctionAttributes(MD, BaseMD);
+ CheckOverridingFunctionExceptionSpec(MD, BaseMD);
+ CheckIfOverriddenFunctionIsMarkedFinal(MD, BaseMD);
}
+
+ // A method can only override one function from each base class. We
+ // don't track indirectly overridden methods from bases of bases.
+ return true;
}
return false;
- }
-};
-} // end anonymous namespace
-
-/// 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 methods in base classes that this method might override.
- CXXBasePaths Paths;
- FindOverriddenMethod FOM;
- FOM.Method = MD;
- FOM.S = this;
- bool AddedAny = false;
- if (DC->lookupInBases(FOM, Paths)) {
- for (auto *I : Paths.found_decls()) {
- if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(I)) {
- MD->addOverriddenMethod(OldMD->getCanonicalDecl());
- if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
- !CheckOverridingFunctionAttributes(MD, OldMD) &&
- !CheckOverridingFunctionExceptionSpec(MD, OldMD) &&
- !CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) {
- AddedAny = true;
- }
- }
- }
- }
+ };
- return AddedAny;
+ DC->lookupInBases(VisitBase, Paths);
+ return !Overridden.empty();
}
namespace {
@@ -8401,7 +8446,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
NewFD = FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), NameInfo,
R, TInfo, SC, isInline, HasPrototype,
- CSK_unspecified,
+ ConstexprSpecKind::Unspecified,
/*TrailingRequiresClause=*/nullptr);
if (D.isInvalidType())
NewFD->setInvalidDecl();
@@ -8412,11 +8457,11 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
ExplicitSpecifier ExplicitSpecifier = D.getDeclSpec().getExplicitSpecifier();
ConstexprSpecKind ConstexprKind = D.getDeclSpec().getConstexprSpecifier();
- if (ConstexprKind == CSK_constinit) {
+ if (ConstexprKind == ConstexprSpecKind::Constinit) {
SemaRef.Diag(D.getDeclSpec().getConstexprSpecLoc(),
diag::err_constexpr_wrong_decl_kind)
- << ConstexprKind;
- ConstexprKind = CSK_unspecified;
+ << static_cast<int>(ConstexprKind);
+ ConstexprKind = ConstexprSpecKind::Unspecified;
D.getMutableDeclSpec().ClearConstexprSpec();
}
Expr *TrailingRequiresClause = D.getTrailingRequiresClause();
@@ -8570,12 +8615,21 @@ static bool isOpenCLSizeDependentType(ASTContext &C, QualType Ty) {
static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
if (PT->isPointerType()) {
QualType PointeeType = PT->getPointeeType();
- if (PointeeType->isPointerType())
- return PtrPtrKernelParam;
if (PointeeType.getAddressSpace() == LangAS::opencl_generic ||
PointeeType.getAddressSpace() == LangAS::opencl_private ||
PointeeType.getAddressSpace() == LangAS::Default)
return InvalidAddrSpacePtrKernelParam;
+
+ if (PointeeType->isPointerType()) {
+ // This is a pointer to pointer parameter.
+ // Recursively check inner type.
+ OpenCLParamType ParamKind = getOpenCLKernelParameterType(S, PointeeType);
+ if (ParamKind == InvalidAddrSpacePtrKernelParam ||
+ ParamKind == InvalidKernelParam)
+ return ParamKind;
+
+ return PtrPtrKernelParam;
+ }
return PtrKernelParam;
}
@@ -8628,11 +8682,17 @@ static void checkIsValidOpenCLKernelParameter(
switch (getOpenCLKernelParameterType(S, PT)) {
case PtrPtrKernelParam:
- // OpenCL v1.2 s6.9.a:
- // A kernel function argument cannot be declared as a
- // pointer to a pointer type.
- S.Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_param);
- D.setInvalidType();
+ // OpenCL v3.0 s6.11.a:
+ // A kernel function argument cannot be declared as a pointer to a pointer
+ // type. [...] This restriction only applies to OpenCL C 1.2 or below.
+ if (S.getLangOpts().OpenCLVersion < 120 &&
+ !S.getLangOpts().OpenCLCPlusPlus) {
+ S.Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_param);
+ D.setInvalidType();
+ return;
+ }
+
+ ValidTypes.insert(PT.getTypePtr());
return;
case InvalidAddrSpacePtrKernelParam:
@@ -8916,13 +8976,13 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
TemplateParamLists, isFriend, isMemberSpecialization,
Invalid);
if (TemplateParams) {
+ // Check that we can declare a template here.
+ if (CheckTemplateDeclScope(S, TemplateParams))
+ NewFD->setInvalidDecl();
+
if (TemplateParams->size() > 0) {
// This is a function template
- // Check that we can declare a template here.
- if (CheckTemplateDeclScope(S, TemplateParams))
- NewFD->setInvalidDecl();
-
// A destructor cannot be a template.
if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
Diag(NewFD->getLocation(), diag::err_destructor_template);
@@ -8981,6 +9041,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
} else {
+ // Check that we can declare a template here.
+ if (!TemplateParamLists.empty() && isMemberSpecialization &&
+ CheckTemplateDeclScope(S, TemplateParamLists.back()))
+ NewFD->setInvalidDecl();
+
// All template param lists were matched against the scope specifier:
// this is NOT (an explicit specialization of) a template.
if (TemplateParamLists.size() > 0)
@@ -9075,8 +9140,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
- if (ConstexprSpecKind ConstexprKind =
- D.getDeclSpec().getConstexprSpecifier()) {
+ ConstexprSpecKind ConstexprKind = D.getDeclSpec().getConstexprSpecifier();
+ if (ConstexprKind != ConstexprSpecKind::Unspecified) {
// C++11 [dcl.constexpr]p2: constexpr functions and constexpr constructors
// are implicitly inline.
NewFD->setImplicitlyInline();
@@ -9085,15 +9150,18 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// be either constructors or to return a literal type. Therefore,
// destructors cannot be declared constexpr.
if (isa<CXXDestructorDecl>(NewFD) &&
- (!getLangOpts().CPlusPlus20 || ConstexprKind == CSK_consteval)) {
+ (!getLangOpts().CPlusPlus20 ||
+ ConstexprKind == ConstexprSpecKind::Consteval)) {
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor)
- << ConstexprKind;
- NewFD->setConstexprKind(getLangOpts().CPlusPlus20 ? CSK_unspecified : CSK_constexpr);
+ << static_cast<int>(ConstexprKind);
+ NewFD->setConstexprKind(getLangOpts().CPlusPlus20
+ ? ConstexprSpecKind::Unspecified
+ : ConstexprSpecKind::Constexpr);
}
// C++20 [dcl.constexpr]p2: An allocation function, or a
// deallocation function shall not be declared with the consteval
// specifier.
- if (ConstexprKind == CSK_consteval &&
+ if (ConstexprKind == ConstexprSpecKind::Consteval &&
(NewFD->getOverloadedOperator() == OO_New ||
NewFD->getOverloadedOperator() == OO_Array_New ||
NewFD->getOverloadedOperator() == OO_Delete ||
@@ -9101,7 +9169,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
Diag(D.getDeclSpec().getConstexprSpecLoc(),
diag::err_invalid_consteval_decl_kind)
<< NewFD;
- NewFD->setConstexprKind(CSK_constexpr);
+ NewFD->setConstexprKind(ConstexprSpecKind::Constexpr);
}
}
@@ -9132,17 +9200,17 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// If a function is defined as defaulted or deleted, mark it as such now.
// We'll do the relevant checks on defaulted / deleted functions later.
switch (D.getFunctionDefinitionKind()) {
- case FDK_Declaration:
- case FDK_Definition:
- break;
+ case FunctionDefinitionKind::Declaration:
+ case FunctionDefinitionKind::Definition:
+ break;
- case FDK_Defaulted:
- NewFD->setDefaulted();
- break;
+ case FunctionDefinitionKind::Defaulted:
+ NewFD->setDefaulted();
+ break;
- case FDK_Deleted:
- NewFD->setDeletedAsWritten();
- break;
+ case FunctionDefinitionKind::Deleted:
+ NewFD->setDeletedAsWritten();
+ break;
}
if (isa<CXXMethodDecl>(NewFD) && DC == CurContext &&
@@ -9459,12 +9527,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// that either the specialized function type or the specialized
// template is dependent, and therefore matching will fail. In
// this case, don't check the specialization yet.
- bool InstantiationDependent = false;
if (isFunctionTemplateSpecialization && isFriend &&
(NewFD->getType()->isDependentType() || DC->isDependentContext() ||
- TemplateSpecializationType::anyDependentTemplateArguments(
- TemplateArgs,
- InstantiationDependent))) {
+ TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
+ TemplateArgs.arguments()))) {
assert(HasExplicitTemplateArgs &&
"friend function specialization without template args");
if (CheckDependentFunctionTemplateSpecialization(NewFD, TemplateArgs,
@@ -9636,6 +9702,36 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
+ // If this is the first declaration of a library builtin function, add
+ // attributes as appropriate.
+ if (!D.isRedeclaration() &&
+ NewFD->getDeclContext()->getRedeclContext()->isFileContext()) {
+ if (IdentifierInfo *II = Previous.getLookupName().getAsIdentifierInfo()) {
+ if (unsigned BuiltinID = II->getBuiltinID()) {
+ if (NewFD->getLanguageLinkage() == CLanguageLinkage) {
+ // Validate the type matches unless this builtin is specified as
+ // matching regardless of its declared type.
+ if (Context.BuiltinInfo.allowTypeMismatch(BuiltinID)) {
+ NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID));
+ } else {
+ ASTContext::GetBuiltinTypeError Error;
+ LookupNecessaryTypesForBuiltin(S, BuiltinID);
+ QualType BuiltinType = Context.GetBuiltinType(BuiltinID, Error);
+
+ if (!Error && !BuiltinType.isNull() &&
+ Context.hasSameFunctionTypeIgnoringExceptionSpec(
+ NewFD->getType(), BuiltinType))
+ NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID));
+ }
+ } else if (BuiltinID == Builtin::BI__GetExceptionInfo &&
+ Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ // FIXME: We should consider this a builtin only in the std namespace.
+ NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID));
+ }
+ }
+ }
+ }
+
ProcessPragmaWeak(S, NewFD);
checkAttributesAfterMerging(*this, *NewFD);
@@ -9813,17 +9909,17 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// because Sema::ActOnStartOfFunctionDef has not been called yet.
if (const auto *NBA = NewFD->getAttr<NoBuiltinAttr>())
switch (D.getFunctionDefinitionKind()) {
- case FDK_Defaulted:
- case FDK_Deleted:
+ case FunctionDefinitionKind::Defaulted:
+ case FunctionDefinitionKind::Deleted:
Diag(NBA->getLocation(),
diag::err_attribute_no_builtin_on_defaulted_deleted_function)
<< NBA->getSpelling();
break;
- case FDK_Declaration:
+ case FunctionDefinitionKind::Declaration:
Diag(NBA->getLocation(), diag::err_attribute_no_builtin_on_non_definition)
<< NBA->getSpelling();
break;
- case FDK_Definition:
+ case FunctionDefinitionKind::Definition:
break;
}
@@ -9996,31 +10092,50 @@ static bool CheckMultiVersionValue(Sema &S, const FunctionDecl *FD) {
// multiversion functions.
static bool AttrCompatibleWithMultiVersion(attr::Kind Kind,
MultiVersionKind MVType) {
+ // Note: this list/diagnosis must match the list in
+ // checkMultiversionAttributesAllSame.
switch (Kind) {
default:
return false;
case attr::Used:
return MVType == MultiVersionKind::Target;
+ case attr::NonNull:
+ case attr::NoThrow:
+ return true;
}
}
-static bool HasNonMultiVersionAttributes(const FunctionDecl *FD,
- MultiVersionKind MVType) {
+static bool checkNonMultiVersionCompatAttributes(Sema &S,
+ const FunctionDecl *FD,
+ const FunctionDecl *CausedFD,
+ MultiVersionKind MVType) {
+ bool IsCPUSpecificCPUDispatchMVType =
+ MVType == MultiVersionKind::CPUDispatch ||
+ MVType == MultiVersionKind::CPUSpecific;
+ const auto Diagnose = [FD, CausedFD, IsCPUSpecificCPUDispatchMVType](
+ Sema &S, const Attr *A) {
+ S.Diag(FD->getLocation(), diag::err_multiversion_disallowed_other_attr)
+ << IsCPUSpecificCPUDispatchMVType << A;
+ if (CausedFD)
+ S.Diag(CausedFD->getLocation(), diag::note_multiversioning_caused_here);
+ return true;
+ };
+
for (const Attr *A : FD->attrs()) {
switch (A->getKind()) {
case attr::CPUDispatch:
case attr::CPUSpecific:
if (MVType != MultiVersionKind::CPUDispatch &&
MVType != MultiVersionKind::CPUSpecific)
- return true;
+ return Diagnose(S, A);
break;
case attr::Target:
if (MVType != MultiVersionKind::Target)
- return true;
+ return Diagnose(S, A);
break;
default:
if (!AttrCompatibleWithMultiVersion(A->getKind(), MVType))
- return true;
+ return Diagnose(S, A);
break;
}
}
@@ -10154,18 +10269,12 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
MVType == MultiVersionKind::CPUDispatch ||
MVType == MultiVersionKind::CPUSpecific;
- // For now, disallow all other attributes. These should be opt-in, but
- // an analysis of all of them is a future FIXME.
- if (CausesMV && OldFD && HasNonMultiVersionAttributes(OldFD, MVType)) {
- S.Diag(OldFD->getLocation(), diag::err_multiversion_no_other_attrs)
- << IsCPUSpecificCPUDispatchMVType;
- S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
+ if (CausesMV && OldFD &&
+ checkNonMultiVersionCompatAttributes(S, OldFD, NewFD, MVType))
return true;
- }
- if (HasNonMultiVersionAttributes(NewFD, MVType))
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_no_other_attrs)
- << IsCPUSpecificCPUDispatchMVType;
+ if (checkNonMultiVersionCompatAttributes(S, NewFD, nullptr, MVType))
+ return true;
// Only allow transition to MultiVersion if it hasn't been used.
if (OldFD && CausesMV && OldFD->isUsed(false))
@@ -10618,6 +10727,12 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
MergeTypeWithPrevious, Previous))
return Redeclaration;
+ // PPC MMA non-pointer types are not allowed as function return types.
+ if (Context.getTargetInfo().getTriple().isPPC64() &&
+ CheckPPCMMAType(NewFD->getReturnType(), NewFD->getLocation())) {
+ NewFD->setInvalidDecl();
+ }
+
// 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.
@@ -10680,7 +10795,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
NewTemplateDecl->mergePrevDecl(OldTemplateDecl);
NewFD->setPreviousDeclaration(OldFD);
- adjustDeclContextForDeclaratorDecl(NewFD, OldFD);
if (NewFD->isCXXClassMember()) {
NewFD->setAccess(OldTemplateDecl->getAccess());
NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
@@ -10707,7 +10821,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
auto *OldFD = cast<FunctionDecl>(OldDecl);
// This needs to happen first so that 'inline' propagates.
NewFD->setPreviousDeclaration(OldFD);
- adjustDeclContextForDeclaratorDecl(NewFD, OldFD);
if (NewFD->isCXXClassMember())
NewFD->setAccess(OldFD->getAccess());
}
@@ -10737,6 +10850,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
}
}
+ if (LangOpts.OpenMP)
+ ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(NewFD);
+
// Semantic checking for this function declaration (in isolation).
if (getLangOpts().CPlusPlus) {
@@ -10815,7 +10931,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// declaration against the expected type for the builtin.
if (unsigned BuiltinID = NewFD->getBuiltinID()) {
ASTContext::GetBuiltinTypeError Error;
- LookupPredefedObjCSuperType(*this, S, NewFD->getIdentifier());
+ LookupNecessaryTypesForBuiltin(S, BuiltinID);
QualType T = Context.GetBuiltinType(BuiltinID, Error);
// If the type of the builtin differs only in its exception
// specification, that's OK.
@@ -10911,7 +11027,7 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_main)
<< FD->isConsteval()
<< FixItHint::CreateRemoval(DS.getConstexprSpecLoc());
- FD->setConstexprKind(CSK_unspecified);
+ FD->setConstexprKind(ConstexprSpecKind::Unspecified);
}
if (getLangOpts().OpenCL) {
@@ -11067,8 +11183,14 @@ bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
// except that the aforementioned are allowed in unevaluated
// expressions. Everything else falls under the
// "may accept other forms of constant expressions" exception.
- // (We never end up here for C++, so the constant expression
- // rules there don't matter.)
+ //
+ // Regular C++ code will not end up here (exceptions: language extensions,
+ // OpenCL C++ etc), so the constant expression rules there don't matter.
+ if (Init->isValueDependent()) {
+ assert(Init->containsErrors() &&
+ "Dependent code should only occur in error-recovery path.");
+ return true;
+ }
const Expr *Culprit;
if (Init->isConstantInitializer(Context, false, &Culprit))
return false;
@@ -12033,7 +12155,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
// Try to correct any TypoExprs in the initialization arguments.
for (size_t Idx = 0; Idx < Args.size(); ++Idx) {
ExprResult Res = CorrectDelayedTyposInExpr(
- Args[Idx], VDecl, /*RecoverUncorrectedTypos=*/false,
+ Args[Idx], VDecl, /*RecoverUncorrectedTypos=*/true,
[this, Entity, Kind](Expr *E) {
InitializationSequence Init(*this, Entity, Kind, MultiExprArg(E));
return Init.Failed() ? ExprError() : E;
@@ -12402,7 +12524,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
!Context.getTargetInfo().getCXXABI().isMicrosoft()) {
Diag(Var->getLocation(),
diag::err_constexpr_static_mem_var_requires_init)
- << Var->getDeclName();
+ << Var;
Var->setInvalidDecl();
return;
}
@@ -12424,6 +12546,17 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
}
if (!Var->isInvalidDecl() && RealDecl->hasAttr<LoaderUninitializedAttr>()) {
+ if (Var->getStorageClass() == SC_Extern) {
+ Diag(Var->getLocation(), diag::err_loader_uninitialized_extern_decl)
+ << Var;
+ Var->setInvalidDecl();
+ return;
+ }
+ if (RequireCompleteType(Var->getLocation(), Var->getType(),
+ diag::err_typecheck_decl_incomplete_type)) {
+ Var->setInvalidDecl();
+ return;
+ }
if (CXXRecordDecl *RD = Var->getType()->getAsCXXRecordDecl()) {
if (!RD->hasTrivialDefaultConstructor()) {
Diag(Var->getLocation(), diag::err_loader_uninitialized_trivial_ctor);
@@ -12431,12 +12564,6 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
return;
}
}
- if (Var->getStorageClass() == SC_Extern) {
- Diag(Var->getLocation(), diag::err_loader_uninitialized_extern_decl)
- << Var;
- Var->setInvalidDecl();
- return;
- }
}
VarDecl::DefinitionKind DefKind = Var->isThisDeclarationADefinition();
@@ -12535,8 +12662,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
// definitions with reference type.
if (Type->isReferenceType()) {
Diag(Var->getLocation(), diag::err_reference_var_requires_init)
- << Var->getDeclName()
- << SourceRange(Var->getLocation(), Var->getLocation());
+ << Var << SourceRange(Var->getLocation(), Var->getLocation());
Var->setInvalidDecl();
return;
}
@@ -12667,9 +12793,21 @@ void Sema::ActOnCXXForRangeDecl(Decl *D) {
Error = 4;
break;
}
+
+ // for-range-declaration cannot be given a storage class specifier con't.
+ switch (VD->getTSCSpec()) {
+ case TSCS_thread_local:
+ Error = 6;
+ break;
+ case TSCS___thread:
+ case TSCS__Thread_local:
+ case TSCS_unspecified:
+ break;
+ }
+
if (Error != -1) {
Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class)
- << VD->getDeclName() << Error;
+ << VD << Error;
D->setInvalidDecl();
}
}
@@ -12691,7 +12829,7 @@ Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc,
DS.SetTypeSpecType(DeclSpec::TST_auto, IdentLoc, PrevSpec, DiagID,
getPrintingPolicy());
- Declarator D(DS, DeclaratorContext::ForContext);
+ Declarator D(DS, DeclaratorContext::ForInit);
D.SetIdentifier(Ident, IdentLoc);
D.takeAttributes(Attrs, AttrEnd);
@@ -12835,20 +12973,64 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
AttributeCommonInfo::AS_Pragma));
}
+ if (!var->getType()->isStructureType() && var->hasInit() &&
+ isa<InitListExpr>(var->getInit())) {
+ const auto *ILE = cast<InitListExpr>(var->getInit());
+ unsigned NumInits = ILE->getNumInits();
+ if (NumInits > 2)
+ for (unsigned I = 0; I < NumInits; ++I) {
+ const auto *Init = ILE->getInit(I);
+ if (!Init)
+ break;
+ const auto *SL = dyn_cast<StringLiteral>(Init->IgnoreImpCasts());
+ if (!SL)
+ break;
+
+ unsigned NumConcat = SL->getNumConcatenated();
+ // Diagnose missing comma in string array initialization.
+ // Do not warn when all the elements in the initializer are concatenated
+ // together. Do not warn for macros too.
+ if (NumConcat == 2 && !SL->getBeginLoc().isMacroID()) {
+ bool OnlyOneMissingComma = true;
+ for (unsigned J = I + 1; J < NumInits; ++J) {
+ const auto *Init = ILE->getInit(J);
+ if (!Init)
+ break;
+ const auto *SLJ = dyn_cast<StringLiteral>(Init->IgnoreImpCasts());
+ if (!SLJ || SLJ->getNumConcatenated() > 1) {
+ OnlyOneMissingComma = false;
+ break;
+ }
+ }
+
+ if (OnlyOneMissingComma) {
+ SmallVector<FixItHint, 1> Hints;
+ for (unsigned i = 0; i < NumConcat - 1; ++i)
+ Hints.push_back(FixItHint::CreateInsertion(
+ PP.getLocForEndOfToken(SL->getStrTokenLoc(i)), ","));
+
+ Diag(SL->getStrTokenLoc(1),
+ diag::warn_concatenated_literal_array_init)
+ << Hints;
+ Diag(SL->getBeginLoc(),
+ diag::note_concatenated_string_literal_silence);
+ }
+ // In any case, stop now.
+ break;
+ }
+ }
+ }
+
// All the following checks are C++ only.
if (!getLangOpts().CPlusPlus) {
- // If this variable must be emitted, add it as an initializer for the
- // current module.
- if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty())
- Context.addModuleInitializer(ModuleScopes.back().Module, var);
- return;
+ // If this variable must be emitted, add it as an initializer for the
+ // current module.
+ if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty())
+ Context.addModuleInitializer(ModuleScopes.back().Module, var);
+ return;
}
- if (auto *DD = dyn_cast<DecompositionDecl>(var))
- CheckCompleteDecompositionDeclaration(DD);
-
QualType type = var->getType();
- if (type->isDependentType()) return;
if (var->hasAttr<BlocksAttr>())
getCurFunction()->addByrefBlockVar(var);
@@ -12857,79 +13039,93 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
bool IsGlobal = GlobalStorage && !var->isStaticLocal();
QualType baseType = Context.getBaseElementType(type);
- if (Init && !Init->isValueDependent()) {
- if (var->isConstexpr()) {
- SmallVector<PartialDiagnosticAt, 8> Notes;
- if (!var->evaluateValue(Notes) || !var->isInitICE()) {
- SourceLocation DiagLoc = var->getLocation();
- // If the note doesn't add any useful information other than a source
- // location, fold it into the primary diagnostic.
- if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
- diag::note_invalid_subexpr_in_const_expr) {
- DiagLoc = Notes[0].first;
- Notes.clear();
- }
- Diag(DiagLoc, diag::err_constexpr_var_requires_const_init)
- << var << Init->getSourceRange();
- for (unsigned I = 0, N = Notes.size(); I != N; ++I)
- Diag(Notes[I].first, Notes[I].second);
+ // Check whether the initializer is sufficiently constant.
+ if (!type->isDependentType() && Init && !Init->isValueDependent() &&
+ (GlobalStorage || var->isConstexpr() ||
+ var->mightBeUsableInConstantExpressions(Context))) {
+ // If this variable might have a constant initializer or might be usable in
+ // constant expressions, check whether or not it actually is now. We can't
+ // do this lazily, because the result might depend on things that change
+ // later, such as which constexpr functions happen to be defined.
+ SmallVector<PartialDiagnosticAt, 8> Notes;
+ bool HasConstInit;
+ if (!getLangOpts().CPlusPlus11) {
+ // Prior to C++11, in contexts where a constant initializer is required,
+ // the set of valid constant initializers is described by syntactic rules
+ // in [expr.const]p2-6.
+ // FIXME: Stricter checking for these rules would be useful for constinit /
+ // -Wglobal-constructors.
+ HasConstInit = checkConstInit();
+
+ // Compute and cache the constant value, and remember that we have a
+ // constant initializer.
+ if (HasConstInit) {
+ (void)var->checkForConstantInitialization(Notes);
+ Notes.clear();
+ } else if (CacheCulprit) {
+ Notes.emplace_back(CacheCulprit->getExprLoc(),
+ PDiag(diag::note_invalid_subexpr_in_const_expr));
+ Notes.back().second << CacheCulprit->getSourceRange();
}
- } else if (var->mightBeUsableInConstantExpressions(Context)) {
- // Check whether the initializer of a const variable of integral or
- // enumeration type is an ICE now, since we can't tell whether it was
- // initialized by a constant expression if we check later.
- var->checkInitIsICE();
- }
-
- // Don't emit further diagnostics about constexpr globals since they
- // were just diagnosed.
- if (!var->isConstexpr() && GlobalStorage && var->hasAttr<ConstInitAttr>()) {
- // FIXME: Need strict checking in C++03 here.
- bool DiagErr = getLangOpts().CPlusPlus11
- ? !var->checkInitIsICE() : !checkConstInit();
- if (DiagErr) {
- auto *Attr = var->getAttr<ConstInitAttr>();
- Diag(var->getLocation(), diag::err_require_constant_init_failed)
- << Init->getSourceRange();
- Diag(Attr->getLocation(),
- diag::note_declared_required_constant_init_here)
- << Attr->getRange() << Attr->isConstinit();
- if (getLangOpts().CPlusPlus11) {
- APValue Value;
- SmallVector<PartialDiagnosticAt, 8> Notes;
- Init->EvaluateAsInitializer(Value, getASTContext(), var, Notes);
- for (auto &it : Notes)
- Diag(it.first, it.second);
- } else {
- Diag(CacheCulprit->getExprLoc(),
- diag::note_invalid_subexpr_in_const_expr)
- << CacheCulprit->getSourceRange();
- }
+ } else {
+ // Evaluate the initializer to see if it's a constant initializer.
+ HasConstInit = var->checkForConstantInitialization(Notes);
+ }
+
+ if (HasConstInit) {
+ // FIXME: Consider replacing the initializer with a ConstantExpr.
+ } else if (var->isConstexpr()) {
+ SourceLocation DiagLoc = var->getLocation();
+ // If the note doesn't add any useful information other than a source
+ // location, fold it into the primary diagnostic.
+ if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
+ diag::note_invalid_subexpr_in_const_expr) {
+ DiagLoc = Notes[0].first;
+ Notes.clear();
}
- }
- else if (!var->isConstexpr() && IsGlobal &&
- !getDiagnostics().isIgnored(diag::warn_global_constructor,
- var->getLocation())) {
+ Diag(DiagLoc, diag::err_constexpr_var_requires_const_init)
+ << var << Init->getSourceRange();
+ for (unsigned I = 0, N = Notes.size(); I != N; ++I)
+ Diag(Notes[I].first, Notes[I].second);
+ } else if (GlobalStorage && var->hasAttr<ConstInitAttr>()) {
+ auto *Attr = var->getAttr<ConstInitAttr>();
+ Diag(var->getLocation(), diag::err_require_constant_init_failed)
+ << Init->getSourceRange();
+ Diag(Attr->getLocation(), diag::note_declared_required_constant_init_here)
+ << Attr->getRange() << Attr->isConstinit();
+ for (auto &it : Notes)
+ Diag(it.first, it.second);
+ } else if (IsGlobal &&
+ !getDiagnostics().isIgnored(diag::warn_global_constructor,
+ var->getLocation())) {
// Warn about globals which don't have a constant initializer. Don't
// warn about globals with a non-trivial destructor because we already
// warned about them.
CXXRecordDecl *RD = baseType->getAsCXXRecordDecl();
if (!(RD && !RD->hasTrivialDestructor())) {
+ // checkConstInit() here permits trivial default initialization even in
+ // C++11 onwards, where such an initializer is not a constant initializer
+ // but nonetheless doesn't require a global constructor.
if (!checkConstInit())
Diag(var->getLocation(), diag::warn_global_constructor)
- << Init->getSourceRange();
+ << Init->getSourceRange();
}
}
}
// Require the destructor.
- if (const RecordType *recordType = baseType->getAs<RecordType>())
- FinalizeVarWithDestructor(var, recordType);
+ if (!type->isDependentType())
+ if (const RecordType *recordType = baseType->getAs<RecordType>())
+ FinalizeVarWithDestructor(var, recordType);
// If this variable must be emitted, add it as an initializer for the current
// module.
if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty())
Context.addModuleInitializer(ModuleScopes.back().Module, var);
+
+ // Build the bindings if this is a structured binding declaration.
+ if (auto *DD = dyn_cast<DecompositionDecl>(var))
+ CheckCompleteDecompositionDeclaration(DD);
}
/// Determines if a variable's alignment is dependent.
@@ -13041,32 +13237,9 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) {
}
}
- if (VD->isStaticLocal()) {
+ if (VD->isStaticLocal())
CheckStaticLocalForDllExport(VD);
- if (dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod())) {
- // CUDA 8.0 E.3.9.4: Within the body of a __device__ or __global__
- // function, only __shared__ variables or variables without any device
- // memory qualifiers may be declared with static storage class.
- // Note: It is unclear how a function-scope non-const static variable
- // without device memory qualifier is implemented, therefore only static
- // const variable without device memory qualifier is allowed.
- [&]() {
- if (!getLangOpts().CUDA)
- return;
- if (VD->hasAttr<CUDASharedAttr>())
- return;
- if (VD->getType().isConstQualified() &&
- !(VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>()))
- return;
- if (CUDADiagIfDeviceCode(VD->getLocation(),
- diag::err_device_static_local_var)
- << CurrentCUDATarget())
- VD->setInvalidDecl();
- }();
- }
- }
-
// Perform check for initializers of device-side global variables.
// CUDA allows empty constructors as initializers (see E.2.3.1, CUDA
// 7.5). We must also apply the same checks to all __shared__
@@ -13144,20 +13317,20 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) {
if (!MagicValueExpr) {
continue;
}
- llvm::APSInt MagicValueInt;
- if (!MagicValueExpr->isIntegerConstantExpr(MagicValueInt, Context)) {
+ Optional<llvm::APSInt> MagicValueInt;
+ if (!(MagicValueInt = MagicValueExpr->getIntegerConstantExpr(Context))) {
Diag(I->getRange().getBegin(),
diag::err_type_tag_for_datatype_not_ice)
<< LangOpts.CPlusPlus << MagicValueExpr->getSourceRange();
continue;
}
- if (MagicValueInt.getActiveBits() > 64) {
+ if (MagicValueInt->getActiveBits() > 64) {
Diag(I->getRange().getBegin(),
diag::err_type_tag_for_datatype_too_large)
<< LangOpts.CPlusPlus << MagicValueExpr->getSourceRange();
continue;
}
- uint64_t MagicValue = MagicValueInt.getZExtValue();
+ uint64_t MagicValue = MagicValueInt->getZExtValue();
RegisterTypeTagForDatatype(I->getArgumentKind(),
MagicValue,
I->getMatchingCType(),
@@ -13392,7 +13565,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
<< getLangOpts().CPlusPlus17;
if (DS.hasConstexprSpecifier())
Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr)
- << 0 << D.getDeclSpec().getConstexprSpecifier();
+ << 0 << static_cast<int>(D.getDeclSpec().getConstexprSpecifier());
DiagnoseFunctionSpecifiers(DS);
@@ -13450,9 +13623,8 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
if (D.getDeclSpec().isModulePrivateSpecified())
Diag(New->getLocation(), diag::err_module_private_local)
- << 1 << New->getDeclName()
- << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
- << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
+ << 1 << New << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
+ << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
if (New->hasAttr<BlocksAttr>()) {
Diag(New->getLocation(), diag::err_block_on_nonlocal);
@@ -13504,8 +13676,7 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue(
if (!ReturnTy->isDependentType() && ReturnTy.isPODType(Context)) {
unsigned Size = Context.getTypeSizeInChars(ReturnTy).getQuantity();
if (Size > LangOpts.NumLargeByValueCopy)
- Diag(D->getLocation(), diag::warn_return_value_size)
- << D->getDeclName() << Size;
+ Diag(D->getLocation(), diag::warn_return_value_size) << D << Size;
}
// Warn if any parameter is pass-by-value and larger than the specified
@@ -13517,7 +13688,7 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue(
unsigned Size = Context.getTypeSizeInChars(T).getQuantity();
if (Size > LangOpts.NumLargeByValueCopy)
Diag(Parameter->getLocation(), diag::warn_parameter_size)
- << Parameter->getDeclName() << Size;
+ << Parameter << Size;
}
}
@@ -13601,6 +13772,12 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
New->setInvalidDecl();
}
+ // PPC MMA non-pointer types are not allowed as function argument types.
+ if (Context.getTargetInfo().getTriple().isPPC64() &&
+ CheckPPCMMAType(New->getOriginalType(), New->getLocation())) {
+ New->setInvalidDecl();
+ }
+
return New;
}
@@ -13632,7 +13809,7 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
// Use the identifier location for the type source range.
DS.SetRangeStart(FTI.Params[i].IdentLoc);
DS.SetRangeEnd(FTI.Params[i].IdentLoc);
- Declarator ParamD(DS, DeclaratorContext::KNRTypeListContext);
+ Declarator ParamD(DS, DeclaratorContext::KNRTypeList);
ParamD.SetIdentifier(FTI.Params[i].Ident, FTI.Params[i].IdentLoc);
FTI.Params[i].Param = ActOnParamDeclarator(S, ParamD);
}
@@ -13655,19 +13832,17 @@ Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D,
// variant` annotation which specifies the mangled definition as a
// specialization function under the OpenMP context defined as part of the
// `omp begin declare variant`.
- FunctionDecl *BaseFD = nullptr;
- if (LangOpts.OpenMP && isInOpenMPDeclareVariantScope() &&
- TemplateParameterLists.empty())
- BaseFD = ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
- ParentScope, D);
+ SmallVector<FunctionDecl *, 4> Bases;
+ if (LangOpts.OpenMP && isInOpenMPDeclareVariantScope())
+ ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
+ ParentScope, D, TemplateParameterLists, Bases);
- D.setFunctionDefinitionKind(FDK_Definition);
+ D.setFunctionDefinitionKind(FunctionDefinitionKind::Definition);
Decl *DP = HandleDeclarator(ParentScope, D, TemplateParameterLists);
Decl *Dcl = ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody);
- if (BaseFD)
- ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
- cast<FunctionDecl>(Dcl), BaseFD);
+ if (!Bases.empty())
+ ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Dcl, Bases);
return Dcl;
}
@@ -13736,69 +13911,23 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
const FunctionDecl *EffectiveDefinition,
SkipBodyInfo *SkipBody) {
const FunctionDecl *Definition = EffectiveDefinition;
- if (!Definition && !FD->isDefined(Definition) && !FD->isCXXClassMember()) {
- // If this is a friend function defined in a class template, it does not
- // have a body until it is used, nevertheless it is a definition, see
- // [temp.inst]p2:
- //
- // ... for the purpose of determining whether an instantiated redeclaration
- // is valid according to [basic.def.odr] and [class.mem], a declaration that
- // corresponds to a definition in the template is considered to be a
- // definition.
- //
- // The following code must produce redefinition error:
- //
- // template<typename T> struct C20 { friend void func_20() {} };
- // C20<int> c20i;
- // void func_20() {}
- //
- for (auto I : FD->redecls()) {
- if (I != FD && !I->isInvalidDecl() &&
- I->getFriendObjectKind() != Decl::FOK_None) {
- if (FunctionDecl *Original = I->getInstantiatedFromMemberFunction()) {
- if (FunctionDecl *OrigFD = FD->getInstantiatedFromMemberFunction()) {
- // A merged copy of the same function, instantiated as a member of
- // the same class, is OK.
- if (declaresSameEntity(OrigFD, Original) &&
- declaresSameEntity(cast<Decl>(I->getLexicalDeclContext()),
- cast<Decl>(FD->getLexicalDeclContext())))
- continue;
- }
+ if (!Definition &&
+ !FD->isDefined(Definition, /*CheckForPendingFriendDefinition*/ true))
+ return;
- if (Original->isThisDeclarationADefinition()) {
- Definition = I;
- break;
- }
- }
+ if (Definition->getFriendObjectKind() != Decl::FOK_None) {
+ if (FunctionDecl *OrigDef = Definition->getInstantiatedFromMemberFunction()) {
+ if (FunctionDecl *OrigFD = FD->getInstantiatedFromMemberFunction()) {
+ // A merged copy of the same function, instantiated as a member of
+ // the same class, is OK.
+ if (declaresSameEntity(OrigFD, OrigDef) &&
+ declaresSameEntity(cast<Decl>(Definition->getLexicalDeclContext()),
+ cast<Decl>(FD->getLexicalDeclContext())))
+ return;
}
}
}
- if (!Definition)
- // Similar to friend functions a friend function template may be a
- // definition and do not have a body if it is instantiated in a class
- // template.
- if (FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate()) {
- for (auto I : FTD->redecls()) {
- auto D = cast<FunctionTemplateDecl>(I);
- if (D != FTD) {
- assert(!D->isThisDeclarationADefinition() &&
- "More than one definition in redeclaration chain");
- if (D->getFriendObjectKind() != Decl::FOK_None)
- if (FunctionTemplateDecl *FT =
- D->getInstantiatedFromMemberTemplate()) {
- if (FT->isThisDeclarationADefinition()) {
- Definition = D->getTemplatedDecl();
- break;
- }
- }
- }
- }
- }
-
- if (!Definition)
- return;
-
if (canRedefineFunction(Definition, getLangOpts()))
return;
@@ -13825,9 +13954,9 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
if (getLangOpts().GNUMode && Definition->isInlineSpecified() &&
Definition->getStorageClass() == SC_Extern)
Diag(FD->getLocation(), diag::err_redefinition_extern_inline)
- << FD->getDeclName() << getLangOpts().CPlusPlus;
+ << FD << getLangOpts().CPlusPlus;
else
- Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName();
+ Diag(FD->getLocation(), diag::err_redefinition) << FD;
Diag(Definition->getLocation(), diag::note_previous_definition);
FD->setInvalidDecl();
@@ -13916,9 +14045,20 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
FD->setInvalidDecl();
}
- // See if this is a redefinition. If 'will have body' is already set, then
- // these checks were already performed when it was set.
- if (!FD->willHaveBody() && !FD->isLateTemplateParsed()) {
+ if (auto *Ctor = dyn_cast<CXXConstructorDecl>(FD)) {
+ if (Ctor->getTemplateSpecializationKind() == TSK_ExplicitSpecialization &&
+ Ctor->isDefaultConstructor() &&
+ Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ // If this is an MS ABI dllexport default constructor, instantiate any
+ // default arguments.
+ InstantiateDefaultCtorDefaultArgs(Ctor);
+ }
+ }
+
+ // See if this is a redefinition. If 'will have body' (or similar) is already
+ // set, then these checks were already performed when it was set.
+ if (!FD->willHaveBody() && !FD->isLateTemplateParsed() &&
+ !FD->isThisDeclarationInstantiatedFromAFriendDefinition()) {
CheckForFunctionRedefinition(FD, nullptr, SkipBody);
// If we're skipping the body, we're done. Don't enter the scope.
@@ -14158,12 +14298,16 @@ static void diagnoseImplicitlyRetainedSelf(Sema &S) {
Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
bool IsInstantiation) {
+ FunctionScopeInfo *FSI = getCurFunction();
FunctionDecl *FD = dcl ? dcl->getAsFunction() : nullptr;
+ if (FSI->UsesFPIntrin && !FD->hasAttr<StrictFPAttr>())
+ FD->addAttr(StrictFPAttr::CreateImplicit(Context));
+
sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
sema::AnalysisBasedWarnings::Policy *ActivePolicy = nullptr;
- if (getLangOpts().Coroutines && getCurFunction()->isCoroutine())
+ if (getLangOpts().Coroutines && FSI->isCoroutine())
CheckCompletedCoroutineBody(FD, Body);
// Do not call PopExpressionEvaluationContext() if it is a lambda because one
@@ -14240,7 +14384,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
// to deduce an implicit return type.
if (FD->getReturnType()->isRecordType() &&
(!getLangOpts().CPlusPlus || !FD->isDependentContext()))
- computeNRVO(Body, getCurFunction());
+ computeNRVO(Body, FSI);
}
// GNU warning -Wmissing-prototypes:
@@ -14364,14 +14508,14 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
MD->getReturnType(), MD);
if (Body)
- computeNRVO(Body, getCurFunction());
+ computeNRVO(Body, FSI);
}
- if (getCurFunction()->ObjCShouldCallSuper) {
+ if (FSI->ObjCShouldCallSuper) {
Diag(MD->getEndLoc(), diag::warn_objc_missing_super_call)
<< MD->getSelector().getAsString();
- getCurFunction()->ObjCShouldCallSuper = false;
+ FSI->ObjCShouldCallSuper = false;
}
- if (getCurFunction()->ObjCWarnForNoDesignatedInitChain) {
+ if (FSI->ObjCWarnForNoDesignatedInitChain) {
const ObjCMethodDecl *InitMethod = nullptr;
bool isDesignated =
MD->isDesignatedInitializerForTheInterface(&InitMethod);
@@ -14396,14 +14540,14 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
Diag(InitMethod->getLocation(),
diag::note_objc_designated_init_marked_here);
}
- getCurFunction()->ObjCWarnForNoDesignatedInitChain = false;
+ FSI->ObjCWarnForNoDesignatedInitChain = false;
}
- if (getCurFunction()->ObjCWarnForNoInitDelegation) {
+ if (FSI->ObjCWarnForNoInitDelegation) {
// Don't issue this warning for unavaialable inits.
if (!MD->isUnavailable())
Diag(MD->getLocation(),
diag::warn_objc_secondary_init_missing_init_call);
- getCurFunction()->ObjCWarnForNoInitDelegation = false;
+ FSI->ObjCWarnForNoInitDelegation = false;
}
diagnoseImplicitlyRetainedSelf(*this);
@@ -14414,10 +14558,10 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
return nullptr;
}
- if (Body && getCurFunction()->HasPotentialAvailabilityViolations)
+ if (Body && FSI->HasPotentialAvailabilityViolations)
DiagnoseUnguardedAvailabilityViolations(dcl);
- assert(!getCurFunction()->ObjCShouldCallSuper &&
+ assert(!FSI->ObjCShouldCallSuper &&
"This should only be set for ObjC methods, which should have been "
"handled in the block above.");
@@ -14430,7 +14574,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body));
// Verify that gotos and switch cases don't jump into scopes illegally.
- if (getCurFunction()->NeedsScopeChecking() &&
+ if (FSI->NeedsScopeChecking() &&
!PP.isCodeCompletionEnabled())
DiagnoseInvalidJumps(Body);
@@ -14445,11 +14589,11 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
// If any errors have occurred, clear out any temporaries that may have
// been leftover. This ensures that these temporaries won't be picked up for
// deletion in some later function.
- if (getDiagnostics().hasUncompilableErrorOccurred() ||
+ if (hasUncompilableErrorOccurred() ||
getDiagnostics().getSuppressAllDiagnostics()) {
DiscardCleanupsInEvaluationContext();
}
- if (!getDiagnostics().hasUncompilableErrorOccurred() &&
+ if (!hasUncompilableErrorOccurred() &&
!isa<FunctionTemplateDecl>(dcl)) {
// Since the body is valid, issue any analysis-based warnings that are
// enabled.
@@ -14501,11 +14645,11 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
// If any errors have occurred, clear out any temporaries that may have
// been leftover. This ensures that these temporaries won't be picked up for
// deletion in some later function.
- if (getDiagnostics().hasUncompilableErrorOccurred()) {
+ if (hasUncompilableErrorOccurred()) {
DiscardCleanupsInEvaluationContext();
}
- if (LangOpts.OpenMP || LangOpts.CUDA || LangOpts.SYCLIsDevice) {
+ if (FD && (LangOpts.OpenMP || LangOpts.CUDA || LangOpts.SYCLIsDevice)) {
auto ES = getEmissionStatus(FD);
if (ES == Sema::FunctionEmissionStatus::Emitted ||
ES == Sema::FunctionEmissionStatus::Unknown)
@@ -14612,7 +14756,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
(void)Error; // Silence warning.
assert(!Error && "Error setting up implicit decl!");
SourceLocation NoLoc;
- Declarator D(DS, DeclaratorContext::BlockContext);
+ Declarator D(DS, DeclaratorContext::Block);
D.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/false,
/*IsAmbiguous=*/false,
/*LParenLoc=*/NoLoc,
@@ -14882,9 +15026,10 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
if (D.getDeclSpec().isModulePrivateSpecified()) {
if (CurContext->isFunctionOrMethod())
Diag(NewTD->getLocation(), diag::err_module_private_local)
- << 2 << NewTD->getDeclName()
- << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
- << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
+ << 2 << NewTD
+ << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
+ << FixItHint::CreateRemoval(
+ D.getDeclSpec().getModulePrivateSpecLoc());
else
NewTD->setModulePrivate();
}
@@ -15272,6 +15417,10 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
isMemberSpecialization = true;
}
}
+
+ if (!TemplateParameterLists.empty() && isMemberSpecialization &&
+ CheckTemplateDeclScope(S, TemplateParameterLists.back()))
+ return nullptr;
}
// Figure out the underlying type if this a enum declaration. We need to do
@@ -15592,6 +15741,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// type declared by an elaborated-type-specifier. In C that is not correct
// and we should instead merge compatible types found by lookup.
if (getLangOpts().CPlusPlus) {
+ // FIXME: This can perform qualified lookups into function contexts,
+ // which are meaningless.
Previous.setRedeclarationKind(forRedeclarationInCurContext());
LookupQualifiedName(Previous, SearchDC);
} else {
@@ -16309,7 +16460,7 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
return BitWidth;
llvm::APSInt Value;
- ExprResult ICE = VerifyIntegerConstantExpression(BitWidth, &Value);
+ ExprResult ICE = VerifyIntegerConstantExpression(BitWidth, &Value, AllowFold);
if (ICE.isInvalid())
return ICE;
BitWidth = ICE.get();
@@ -16329,6 +16480,13 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
<< Value.toString(10);
}
+ // The size of the bit-field must not exceed our maximum permitted object
+ // size.
+ if (Value.getActiveBits() > ConstantArrayType::getMaxSizeBits(Context)) {
+ return Diag(FieldLoc, diag::err_bitfield_too_wide)
+ << !FieldName << FieldName << Value.toString(10);
+ }
+
if (!FieldTy->isDependentType()) {
uint64_t TypeStorageSize = Context.getTypeSize(FieldTy);
uint64_t TypeWidth = Context.getIntWidth(FieldTy);
@@ -16346,25 +16504,21 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
CStdConstraintViolation ? TypeWidth : TypeStorageSize;
if (FieldName)
return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_width)
- << FieldName << (unsigned)Value.getZExtValue()
+ << FieldName << Value.toString(10)
<< !CStdConstraintViolation << DiagWidth;
return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_width)
- << (unsigned)Value.getZExtValue() << !CStdConstraintViolation
+ << Value.toString(10) << !CStdConstraintViolation
<< DiagWidth;
}
// Warn on types where the user might conceivably expect to get all
// specified bits as value bits: that's all integral types other than
// 'bool'.
- if (BitfieldIsOverwide && !FieldTy->isBooleanType()) {
- if (FieldName)
- Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_width)
- << FieldName << (unsigned)Value.getZExtValue()
- << (unsigned)TypeWidth;
- else
- Diag(FieldLoc, diag::warn_anon_bitfield_width_exceeds_type_width)
- << (unsigned)Value.getZExtValue() << (unsigned)TypeWidth;
+ if (BitfieldIsOverwide && !FieldTy->isBooleanType() && FieldName) {
+ Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_width)
+ << FieldName << Value.toString(10)
+ << (unsigned)TypeWidth;
}
}
@@ -16558,27 +16712,9 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
// C99 6.7.2.1p8: A member of a structure or union may have any type other
// than a variably modified type.
if (!InvalidDecl && T->isVariablyModifiedType()) {
- bool SizeIsNegative;
- llvm::APSInt Oversized;
-
- TypeSourceInfo *FixedTInfo =
- TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context,
- SizeIsNegative,
- Oversized);
- if (FixedTInfo) {
- Diag(Loc, diag::warn_illegal_constant_array_size);
- TInfo = FixedTInfo;
- T = FixedTInfo->getType();
- } else {
- if (SizeIsNegative)
- Diag(Loc, diag::err_typecheck_negative_array_size);
- else if (Oversized.getBoolValue())
- Diag(Loc, diag::err_array_too_large)
- << Oversized.toString(10);
- else
- Diag(Loc, diag::err_typecheck_field_variable_size);
+ if (!tryToFixVariablyModifiedVarType(
+ *this, TInfo, T, Loc, diag::err_typecheck_field_variable_size))
InvalidDecl = true;
- }
}
// Fields can not have abstract class types
@@ -16599,14 +16735,6 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
BitWidth = nullptr;
ZeroWidth = false;
}
-
- // Only data members can have in-class initializers.
- if (BitWidth && !II && InitStyle) {
- Diag(Loc, diag::err_anon_bitfield_init);
- InvalidDecl = true;
- BitWidth = nullptr;
- ZeroWidth = false;
- }
}
// Check that 'mutable' is consistent with the type of the declaration.
@@ -16694,6 +16822,11 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
if (T.isObjCGCWeak())
Diag(Loc, diag::warn_attribute_weak_on_field);
+ // PPC MMA non-pointer types are not allowed as field types.
+ if (Context.getTargetInfo().getTriple().isPPC64() &&
+ CheckPPCMMAType(T, NewFD->getLocation()))
+ NewFD->setInvalidDecl();
+
NewFD->setAccess(AS);
return NewFD;
}
@@ -16807,8 +16940,9 @@ Decl *Sema::ActOnIvar(Scope *S,
// C99 6.7.2.1p8: A member of a structure or union may have any type other
// than a variably modified type.
else if (T->isVariablyModifiedType()) {
- Diag(Loc, diag::err_typecheck_ivar_variable_size);
- D.setInvalidType();
+ if (!tryToFixVariablyModifiedVarType(
+ *this, TInfo, T, Loc, diag::err_typecheck_ivar_variable_size))
+ D.setInvalidType();
}
// Get the visibility (access control) for this ivar.
@@ -17271,7 +17405,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record);
CheckForZeroSize =
CXXRecord->getLexicalDeclContext()->isExternCContext() &&
- !CXXRecord->isDependentType() &&
+ !CXXRecord->isDependentType() && !inTemplateInstantiation() &&
CXXRecord->isCLike();
}
if (CheckForZeroSize) {
@@ -17435,6 +17569,8 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
if (Enum->isDependentType() || Val->isTypeDependent())
EltTy = Context.DependentTy;
else {
+ // FIXME: We don't allow folding in C++11 mode for an enum with a fixed
+ // underlying type, but do allow it in all other contexts.
if (getLangOpts().CPlusPlus11 && Enum->isFixed()) {
// C++11 [dcl.enum]p5: If the underlying type is fixed, [...] the
// constant-expression in the enumerator-definition shall be a converted
@@ -17448,8 +17584,9 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
else
Val = Converted.get();
} else if (!Val->isValueDependent() &&
- !(Val = VerifyIntegerConstantExpression(Val,
- &EnumVal).get())) {
+ !(Val =
+ VerifyIntegerConstantExpression(Val, &EnumVal, AllowFold)
+ .get())) {
// C99 6.7.2.2p2: Make sure we have an integer constant expression.
} else {
if (Enum->isComplete()) {
@@ -18070,11 +18207,9 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
// Adjust the Expr initializer and type.
if (ECD->getInitExpr() &&
!Context.hasSameType(NewTy, ECD->getInitExpr()->getType()))
- ECD->setInitExpr(ImplicitCastExpr::Create(Context, NewTy,
- CK_IntegralCast,
- ECD->getInitExpr(),
- /*base paths*/ nullptr,
- VK_RValue));
+ ECD->setInitExpr(ImplicitCastExpr::Create(
+ Context, NewTy, CK_IntegralCast, ECD->getInitExpr(),
+ /*base paths*/ nullptr, VK_RValue, FPOptionsOverride()));
if (getLangOpts().CPlusPlus)
// C++ [dcl.enum]p4: Following the closing brace of an
// enum-specifier, each enumerator has the type of its
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 1a0594512a60..30d08b3d4ac0 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -21,7 +21,9 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Type.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
@@ -30,12 +32,16 @@
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/IR/Assumptions.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
using namespace clang;
using namespace sema;
@@ -240,9 +246,9 @@ template <typename AttrInfo>
static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr,
uint32_t &Val, unsigned Idx = UINT_MAX,
bool StrictlyUnsigned = false) {
- llvm::APSInt I(32);
+ Optional<llvm::APSInt> I = llvm::APSInt(32);
if (Expr->isTypeDependent() || Expr->isValueDependent() ||
- !Expr->isIntegerConstantExpr(I, S.Context)) {
+ !(I = Expr->getIntegerConstantExpr(S.Context))) {
if (Idx != UINT_MAX)
S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
<< &AI << Idx << AANT_ArgumentIntegerConstant
@@ -253,19 +259,19 @@ static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr,
return false;
}
- if (!I.isIntN(32)) {
+ if (!I->isIntN(32)) {
S.Diag(Expr->getExprLoc(), diag::err_ice_too_large)
- << I.toString(10, false) << 32 << /* Unsigned */ 1;
+ << I->toString(10, false) << 32 << /* Unsigned */ 1;
return false;
}
- if (StrictlyUnsigned && I.isSigned() && I.isNegative()) {
+ if (StrictlyUnsigned && I->isSigned() && I->isNegative()) {
S.Diag(getAttrLoc(AI), diag::err_attribute_requires_positive_integer)
<< &AI << /*non-negative*/ 1;
return false;
}
- Val = (uint32_t)I.getZExtValue();
+ Val = (uint32_t)I->getZExtValue();
return true;
}
@@ -332,16 +338,16 @@ static bool checkFunctionOrMethodParameterIndex(
unsigned NumParams =
(HP ? getFunctionOrMethodNumParams(D) : 0) + HasImplicitThisParam;
- llvm::APSInt IdxInt;
+ Optional<llvm::APSInt> IdxInt;
if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
- !IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) {
+ !(IdxInt = IdxExpr->getIntegerConstantExpr(S.Context))) {
S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
<< &AI << AttrArgNum << AANT_ArgumentIntegerConstant
<< IdxExpr->getSourceRange();
return false;
}
- unsigned IdxSource = IdxInt.getLimitedValue(UINT_MAX);
+ unsigned IdxSource = IdxInt->getLimitedValue(UINT_MAX);
if (IdxSource < 1 || (!IV && IdxSource > NumParams)) {
S.Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds)
<< &AI << AttrArgNum << IdxExpr->getSourceRange();
@@ -1376,6 +1382,43 @@ static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL;
}
+static void handlePreferredName(Sema &S, Decl *D, const ParsedAttr &AL) {
+ auto *RD = cast<CXXRecordDecl>(D);
+ ClassTemplateDecl *CTD = RD->getDescribedClassTemplate();
+ assert(CTD && "attribute does not appertain to this declaration");
+
+ ParsedType PT = AL.getTypeArg();
+ TypeSourceInfo *TSI = nullptr;
+ QualType T = S.GetTypeFromParser(PT, &TSI);
+ if (!TSI)
+ TSI = S.Context.getTrivialTypeSourceInfo(T, AL.getLoc());
+
+ if (!T.hasQualifiers() && T->isTypedefNameType()) {
+ // Find the template name, if this type names a template specialization.
+ const TemplateDecl *Template = nullptr;
+ if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
+ T->getAsCXXRecordDecl())) {
+ Template = CTSD->getSpecializedTemplate();
+ } else if (const auto *TST = T->getAs<TemplateSpecializationType>()) {
+ while (TST && TST->isTypeAlias())
+ TST = TST->getAliasedType()->getAs<TemplateSpecializationType>();
+ if (TST)
+ Template = TST->getTemplateName().getAsTemplateDecl();
+ }
+
+ if (Template && declaresSameEntity(Template, CTD)) {
+ D->addAttr(::new (S.Context) PreferredNameAttr(S.Context, AL, TSI));
+ return;
+ }
+ }
+
+ S.Diag(AL.getLoc(), diag::err_attribute_preferred_name_arg_invalid)
+ << T << CTD;
+ if (const auto *TT = T->getAs<TypedefType>())
+ S.Diag(TT->getDecl()->getLocation(), diag::note_entity_declared_at)
+ << TT->getDecl();
+}
+
static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) {
// The IBOutlet/IBOutletCollection attributes only apply to instance
// variables or properties of Objective-C classes. The outlet must also
@@ -1605,8 +1648,8 @@ void Sema::AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
}
if (!E->isValueDependent()) {
- llvm::APSInt I(64);
- if (!E->isIntegerConstantExpr(I, Context)) {
+ Optional<llvm::APSInt> I = llvm::APSInt(64);
+ if (!(I = E->getIntegerConstantExpr(Context))) {
if (OE)
Diag(AttrLoc, diag::err_attribute_argument_n_type)
<< &TmpAttr << 1 << AANT_ArgumentIntegerConstant
@@ -1618,27 +1661,22 @@ void Sema::AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
return;
}
- if (!I.isPowerOf2()) {
+ if (!I->isPowerOf2()) {
Diag(AttrLoc, diag::err_alignment_not_power_of_two)
<< E->getSourceRange();
return;
}
- if (I > Sema::MaximumAlignment)
+ if (*I > Sema::MaximumAlignment)
Diag(CI.getLoc(), diag::warn_assume_aligned_too_great)
<< CI.getRange() << Sema::MaximumAlignment;
}
- 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;
- }
- }
+ if (OE && !OE->isValueDependent() && !OE->isIntegerConstantExpr(Context)) {
+ Diag(AttrLoc, diag::err_attribute_argument_n_type)
+ << &TmpAttr << 2 << AANT_ArgumentIntegerConstant
+ << OE->getSourceRange();
+ return;
}
D->addAttr(::new (Context) AssumeAlignedAttr(Context, CI, E, OE));
@@ -1676,6 +1714,42 @@ void Sema::AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI,
D->addAttr(::new (Context) AllocAlignAttr(Context, CI, Idx));
}
+/// Check if \p AssumptionStr is a known assumption and warn if not.
+static void checkAssumptionAttr(Sema &S, SourceLocation Loc,
+ StringRef AssumptionStr) {
+ if (llvm::KnownAssumptionStrings.count(AssumptionStr))
+ return;
+
+ unsigned BestEditDistance = 3;
+ StringRef Suggestion;
+ for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) {
+ unsigned EditDistance =
+ AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
+ if (EditDistance < BestEditDistance) {
+ Suggestion = KnownAssumptionIt.getKey();
+ BestEditDistance = EditDistance;
+ }
+ }
+
+ if (!Suggestion.empty())
+ S.Diag(Loc, diag::warn_assume_attribute_string_unknown_suggested)
+ << AssumptionStr << Suggestion;
+ else
+ S.Diag(Loc, diag::warn_assume_attribute_string_unknown) << AssumptionStr;
+}
+
+static void handleAssumumptionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ // Handle the case where the attribute has a text message.
+ StringRef Str;
+ SourceLocation AttrStrLoc;
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
+ return;
+
+ checkAssumptionAttr(S, AttrStrLoc, Str);
+
+ D->addAttr(::new (S.Context) AssumptionAttr(S.Context, AL, Str));
+}
+
/// Normalize the attribute, __foo__ becomes foo.
/// Returns true if normalization was applied.
static bool normalizeName(StringRef &AttrName) {
@@ -2056,7 +2130,8 @@ bool Sema::CheckAttrNoArgs(const ParsedAttr &Attrs) {
bool Sema::CheckAttrTarget(const ParsedAttr &AL) {
// Check whether the attribute is valid on the current target.
if (!AL.existsInTarget(Context.getTargetInfo())) {
- Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL;
+ Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored)
+ << AL << AL.getRange();
AL.setInvalid();
return true;
}
@@ -2618,6 +2693,11 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL,
D->addAttr(newAttr);
}
+static void handleObjCNonRuntimeProtocolAttr(Sema &S, Decl *D,
+ const ParsedAttr &AL) {
+ handleSimpleAttribute<ObjCNonRuntimeProtocolAttr>(S, D, AL);
+}
+
static void handleObjCDirectAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// objc_direct cannot be set on methods declared in the context of a protocol
if (isa<ObjCProtocolDecl>(D->getDeclContext())) {
@@ -2729,36 +2809,36 @@ static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
unsigned sentinel = (unsigned)SentinelAttr::DefaultSentinel;
if (AL.getNumArgs() > 0) {
Expr *E = AL.getArgAsExpr(0);
- llvm::APSInt Idx(32);
+ Optional<llvm::APSInt> Idx = llvm::APSInt(32);
if (E->isTypeDependent() || E->isValueDependent() ||
- !E->isIntegerConstantExpr(Idx, S.Context)) {
+ !(Idx = E->getIntegerConstantExpr(S.Context))) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
<< AL << 1 << AANT_ArgumentIntegerConstant << E->getSourceRange();
return;
}
- if (Idx.isSigned() && Idx.isNegative()) {
+ if (Idx->isSigned() && Idx->isNegative()) {
S.Diag(AL.getLoc(), diag::err_attribute_sentinel_less_than_zero)
<< E->getSourceRange();
return;
}
- sentinel = Idx.getZExtValue();
+ sentinel = Idx->getZExtValue();
}
unsigned nullPos = (unsigned)SentinelAttr::DefaultNullPos;
if (AL.getNumArgs() > 1) {
Expr *E = AL.getArgAsExpr(1);
- llvm::APSInt Idx(32);
+ Optional<llvm::APSInt> Idx = llvm::APSInt(32);
if (E->isTypeDependent() || E->isValueDependent() ||
- !E->isIntegerConstantExpr(Idx, S.Context)) {
+ !(Idx = E->getIntegerConstantExpr(S.Context))) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
<< AL << 2 << AANT_ArgumentIntegerConstant << E->getSourceRange();
return;
}
- nullPos = Idx.getZExtValue();
+ nullPos = Idx->getZExtValue();
- if ((Idx.isSigned() && Idx.isNegative()) || nullPos > 1) {
+ if ((Idx->isSigned() && Idx->isNegative()) || nullPos > 1) {
// FIXME: This error message could be improved, it would be nice
// to say what the bounds actually are.
S.Diag(AL.getLoc(), diag::err_attribute_sentinel_not_zero_or_one)
@@ -3001,8 +3081,14 @@ static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
SectionAttr *NewAttr = S.mergeSectionAttr(D, AL, Str);
- if (NewAttr)
+ if (NewAttr) {
D->addAttr(NewAttr);
+ if (isa<FunctionDecl, FunctionTemplateDecl, ObjCMethodDecl,
+ ObjCPropertyDecl>(D))
+ S.UnifySection(NewAttr->getName(),
+ ASTContext::PSF_Execute | ASTContext::PSF_Read,
+ cast<NamedDecl>(D));
+ }
}
// This is used for `__declspec(code_seg("segname"))` on a decl.
@@ -3063,23 +3149,36 @@ static void handleCodeSegAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Check for things we'd like to warn about. Multiversioning issues are
// handled later in the process, once we know how many exist.
bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
- enum FirstParam { Unsupported, Duplicate };
- enum SecondParam { None, Architecture };
- for (auto Str : {"tune=", "fpmath="})
- if (AttrStr.find(Str) != StringRef::npos)
- return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << Str;
+ enum FirstParam { Unsupported, Duplicate, Unknown };
+ enum SecondParam { None, Architecture, Tune };
+ if (AttrStr.find("fpmath=") != StringRef::npos)
+ return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << "fpmath=";
+
+ // Diagnose use of tune if target doesn't support it.
+ if (!Context.getTargetInfo().supportsTargetAttributeTune() &&
+ AttrStr.find("tune=") != StringRef::npos)
+ return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << "tune=";
ParsedTargetAttr ParsedAttrs = TargetAttr::parse(AttrStr);
if (!ParsedAttrs.Architecture.empty() &&
!Context.getTargetInfo().isValidCPUName(ParsedAttrs.Architecture))
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << Architecture << ParsedAttrs.Architecture;
+ << Unknown << Architecture << ParsedAttrs.Architecture;
+
+ if (!ParsedAttrs.Tune.empty() &&
+ !Context.getTargetInfo().isValidCPUName(ParsedAttrs.Tune))
+ return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
+ << Unknown << Tune << ParsedAttrs.Tune;
if (ParsedAttrs.DuplicateArchitecture)
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Duplicate << None << "arch=";
+ if (ParsedAttrs.DuplicateTune)
+ return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
+ << Duplicate << None << "tune=";
for (const auto &Feature : ParsedAttrs.Features) {
auto CurFeature = StringRef(Feature).drop_front(); // remove + or -.
@@ -3301,7 +3400,11 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
return;
}
- if (prioritynum < 101 || prioritynum > 65535) {
+ // Only perform the priority check if the attribute is outside of a system
+ // header. Values <= 100 are reserved for the implementation, and libc++
+ // benefits from being able to specify values in that range.
+ if ((prioritynum < 101 || prioritynum > 65535) &&
+ !S.getSourceManager().isInSystemHeader(AL.getLoc())) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_range)
<< E->getSourceRange() << AL << 101 << 65535;
AL.setInvalid();
@@ -3590,6 +3693,26 @@ static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
S.Context, AL, EncodingIndices.data(), EncodingIndices.size()));
}
+static bool isFunctionLike(const Type &T) {
+ // Check for explicit function types.
+ // 'called_once' is only supported in Objective-C and it has
+ // function pointers and block pointers.
+ return T.isFunctionPointerType() || T.isBlockPointerType();
+}
+
+/// Handle 'called_once' attribute.
+static void handleCalledOnceAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ // 'called_once' only applies to parameters representing functions.
+ QualType T = cast<ParmVarDecl>(D)->getType();
+
+ if (!isFunctionLike(*T)) {
+ S.Diag(AL.getLoc(), diag::err_called_once_attribute_wrong_type);
+ return;
+ }
+
+ D->addAttr(::new (S.Context) CalledOnceAttr(S.Context, AL));
+}
+
static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Try to find the underlying union declaration.
RecordDecl *RD = nullptr;
@@ -3645,15 +3768,15 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
S.Context.getTypeAlign(FieldType) > FirstAlign) {
// Warn if we drop the attribute.
bool isSize = S.Context.getTypeSize(FieldType) != FirstSize;
- unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType)
- : S.Context.getTypeAlign(FieldType);
+ unsigned FieldBits = isSize ? S.Context.getTypeSize(FieldType)
+ : S.Context.getTypeAlign(FieldType);
S.Diag(Field->getLocation(),
- diag::warn_transparent_union_attribute_field_size_align)
- << isSize << Field->getDeclName() << FieldBits;
- unsigned FirstBits = isSize? FirstSize : FirstAlign;
+ diag::warn_transparent_union_attribute_field_size_align)
+ << isSize << *Field << FieldBits;
+ unsigned FirstBits = isSize ? FirstSize : FirstAlign;
S.Diag(FirstField->getLocation(),
diag::note_transparent_union_first_field_size_align)
- << isSize << FirstBits;
+ << isSize << FirstBits;
return;
}
}
@@ -3661,20 +3784,68 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
RD->addAttr(::new (S.Context) TransparentUnionAttr(S.Context, AL));
}
+void Sema::AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI,
+ StringRef Str, MutableArrayRef<Expr *> Args) {
+ auto *Attr = AnnotateAttr::Create(Context, Str, Args.data(), Args.size(), CI);
+ llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+ for (unsigned Idx = 0; Idx < Attr->args_size(); Idx++) {
+ Expr *&E = Attr->args_begin()[Idx];
+ assert(E && "error are handled before");
+ if (E->isValueDependent() || E->isTypeDependent())
+ continue;
+
+ if (E->getType()->isArrayType())
+ E = ImpCastExprToType(E, Context.getPointerType(E->getType()),
+ clang::CK_ArrayToPointerDecay)
+ .get();
+ if (E->getType()->isFunctionType())
+ E = ImplicitCastExpr::Create(Context,
+ Context.getPointerType(E->getType()),
+ clang::CK_FunctionToPointerDecay, E, nullptr,
+ VK_RValue, FPOptionsOverride());
+ if (E->isLValue())
+ E = ImplicitCastExpr::Create(Context, E->getType().getNonReferenceType(),
+ clang::CK_LValueToRValue, E, nullptr,
+ VK_RValue, FPOptionsOverride());
+
+ Expr::EvalResult Eval;
+ Notes.clear();
+ Eval.Diag = &Notes;
+
+ bool Result =
+ E->EvaluateAsConstantExpr(Eval, Context);
+
+ /// Result means the expression can be folded to a constant.
+ /// Note.empty() means the expression is a valid constant expression in the
+ /// current language mode.
+ if (!Result || !Notes.empty()) {
+ Diag(E->getBeginLoc(), diag::err_attribute_argument_n_type)
+ << CI << (Idx + 1) << AANT_ArgumentConstantExpr;
+ for (auto &Note : Notes)
+ Diag(Note.first, Note.second);
+ return;
+ }
+ assert(Eval.Val.hasValue());
+ E = ConstantExpr::Create(Context, E, Eval.Val);
+ }
+ D->addAttr(Attr);
+}
+
static void handleAnnotateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // Make sure that there is a string literal as the annotation's single
+ // Make sure that there is a string literal as the annotation's first
// argument.
StringRef Str;
if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
return;
- // Don't duplicate annotations that are already set.
- for (const auto *I : D->specific_attrs<AnnotateAttr>()) {
- if (I->getAnnotation() == Str)
- return;
+ llvm::SmallVector<Expr *, 4> Args;
+ Args.reserve(AL.getNumArgs() - 1);
+ for (unsigned Idx = 1; Idx < AL.getNumArgs(); Idx++) {
+ assert(!AL.isArgIdent(Idx));
+ Args.push_back(AL.getArgAsExpr(Idx));
}
- D->addAttr(::new (S.Context) AnnotateAttr(S.Context, AL, Str));
+ S.AddAnnotationAttr(D, AL, Str, Args);
}
static void handleAlignValueAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
@@ -3702,10 +3873,8 @@ void Sema::AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E) {
if (!E->isValueDependent()) {
llvm::APSInt Alignment;
- ExprResult ICE
- = VerifyIntegerConstantExpression(E, &Alignment,
- diag::err_align_value_attribute_argument_not_int,
- /*AllowFold*/ false);
+ ExprResult ICE = VerifyIntegerConstantExpression(
+ E, &Alignment, diag::err_align_value_attribute_argument_not_int);
if (ICE.isInvalid())
return;
@@ -3811,10 +3980,8 @@ void Sema::AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
// FIXME: Cache the number on the AL object?
llvm::APSInt Alignment;
- ExprResult ICE
- = VerifyIntegerConstantExpression(E, &Alignment,
- diag::err_aligned_attribute_argument_not_int,
- /*AllowFold*/ false);
+ ExprResult ICE = VerifyIntegerConstantExpression(
+ E, &Alignment, diag::err_aligned_attribute_argument_not_int);
if (ICE.isInvalid())
return;
@@ -4265,6 +4432,20 @@ NoSpeculativeLoadHardeningAttr *Sema::mergeNoSpeculativeLoadHardeningAttr(
return ::new (Context) NoSpeculativeLoadHardeningAttr(Context, AL);
}
+SwiftNameAttr *Sema::mergeSwiftNameAttr(Decl *D, const SwiftNameAttr &SNA,
+ StringRef Name) {
+ if (const auto *PrevSNA = D->getAttr<SwiftNameAttr>()) {
+ if (PrevSNA->getName() != Name && !PrevSNA->isImplicit()) {
+ Diag(PrevSNA->getLocation(), diag::err_attributes_are_not_compatible)
+ << PrevSNA << &SNA;
+ Diag(SNA.getLoc(), diag::note_conflicting_attribute);
+ }
+
+ D->dropAttr<SwiftNameAttr>();
+ }
+ return ::new (Context) SwiftNameAttr(Context, SNA, Name);
+}
+
OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D,
const AttributeCommonInfo &CI) {
if (AlwaysInlineAttr *Inline = D->getAttr<AlwaysInlineAttr>()) {
@@ -4312,18 +4493,20 @@ static void handleOptimizeNoneAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL))
+ if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL) ||
+ checkAttrMutualExclusion<HIPManagedAttr>(S, D, AL))
return;
const auto *VD = cast<VarDecl>(D);
- if (!VD->hasGlobalStorage()) {
- S.Diag(AL.getLoc(), diag::err_cuda_nonglobal_constant);
+ if (VD->hasLocalStorage()) {
+ S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev);
return;
}
D->addAttr(::new (S.Context) CUDAConstantAttr(S.Context, AL));
}
static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL))
+ if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL) ||
+ checkAttrMutualExclusion<HIPManagedAttr>(S, D, AL))
return;
const auto *VD = cast<VarDecl>(D);
// extern __shared__ is only allowed on arrays with no length (e.g.
@@ -4377,6 +4560,44 @@ static void handleGlobalAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
D->addAttr(NoDebugAttr::CreateImplicit(S.Context));
}
+static void handleDeviceAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (checkAttrMutualExclusion<CUDAGlobalAttr>(S, D, AL)) {
+ return;
+ }
+
+ if (const auto *VD = dyn_cast<VarDecl>(D)) {
+ if (VD->hasLocalStorage()) {
+ S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev);
+ return;
+ }
+ }
+
+ if (auto *A = D->getAttr<CUDADeviceAttr>()) {
+ if (!A->isImplicit())
+ return;
+ D->dropAttr<CUDADeviceAttr>();
+ }
+ D->addAttr(::new (S.Context) CUDADeviceAttr(S.Context, AL));
+}
+
+static void handleManagedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL) ||
+ checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL)) {
+ return;
+ }
+
+ if (const auto *VD = dyn_cast<VarDecl>(D)) {
+ if (VD->hasLocalStorage()) {
+ S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev);
+ return;
+ }
+ }
+ if (!D->hasAttr<HIPManagedAttr>())
+ D->addAttr(::new (S.Context) HIPManagedAttr(S.Context, AL));
+ if (!D->hasAttr<CUDADeviceAttr>())
+ D->addAttr(CUDADeviceAttr::CreateImplicit(S.Context));
+}
+
static void handleGNUInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
const auto *Fn = cast<FunctionDecl>(D);
if (!Fn->isInlineSpecified()) {
@@ -4833,19 +5054,19 @@ static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E,
if (E->isValueDependent())
return E;
- llvm::APSInt I(64);
- if (!E->isIntegerConstantExpr(I, S.Context)) {
+ Optional<llvm::APSInt> I = llvm::APSInt(64);
+ if (!(I = E->getIntegerConstantExpr(S.Context))) {
S.Diag(E->getExprLoc(), diag::err_attribute_argument_n_type)
<< &AL << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange();
return nullptr;
}
// Make sure we can fit it in 32 bits.
- if (!I.isIntN(32)) {
- S.Diag(E->getExprLoc(), diag::err_ice_too_large) << I.toString(10, false)
- << 32 << /* Unsigned */ 1;
+ if (!I->isIntN(32)) {
+ S.Diag(E->getExprLoc(), diag::err_ice_too_large)
+ << I->toString(10, false) << 32 << /* Unsigned */ 1;
return nullptr;
}
- if (I < 0)
+ if (*I < 0)
S.Diag(E->getExprLoc(), diag::warn_attribute_argument_n_negative)
<< &AL << Idx << E->getSourceRange();
@@ -5327,6 +5548,31 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
D->addAttr(::new (S.Context) ObjCRequiresSuperAttr(S.Context, Attrs));
}
+static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &AL) {
+ auto *E = AL.getArgAsExpr(0);
+ auto Loc = E ? E->getBeginLoc() : AL.getLoc();
+
+ auto *DRE = dyn_cast<DeclRefExpr>(AL.getArgAsExpr(0));
+ if (!DRE) {
+ S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
+ return;
+ }
+
+ auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
+ if (!VD) {
+ S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 1 << DRE->getDecl();
+ return;
+ }
+
+ if (!isNSStringType(VD->getType(), S.Context) &&
+ !isCFStringType(VD->getType(), S.Context)) {
+ S.Diag(Loc, diag::err_nserrordomain_wrong_type) << VD;
+ return;
+ }
+
+ D->addAttr(::new (S.Context) NSErrorDomainAttr(S.Context, AL, VD));
+}
+
static void handleObjCBridgeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr;
@@ -5488,6 +5734,515 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
D->addAttr(::new (S.Context) ObjCPreciseLifetimeAttr(S.Context, AL));
}
+static void handleSwiftAttrAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ // Make sure that there is a string literal as the annotation's single
+ // argument.
+ StringRef Str;
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
+ return;
+
+ D->addAttr(::new (S.Context) SwiftAttrAttr(S.Context, AL, Str));
+}
+
+static void handleSwiftBridge(Sema &S, Decl *D, const ParsedAttr &AL) {
+ // Make sure that there is a string literal as the annotation's single
+ // argument.
+ StringRef BT;
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, BT))
+ return;
+
+ // Don't duplicate annotations that are already set.
+ if (D->hasAttr<SwiftBridgeAttr>()) {
+ S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
+ return;
+ }
+
+ D->addAttr(::new (S.Context) SwiftBridgeAttr(S.Context, AL, BT));
+}
+
+static bool isErrorParameter(Sema &S, QualType QT) {
+ const auto *PT = QT->getAs<PointerType>();
+ if (!PT)
+ return false;
+
+ QualType Pointee = PT->getPointeeType();
+
+ // Check for NSError**.
+ if (const auto *OPT = Pointee->getAs<ObjCObjectPointerType>())
+ if (const auto *ID = OPT->getInterfaceDecl())
+ if (ID->getIdentifier() == S.getNSErrorIdent())
+ return true;
+
+ // Check for CFError**.
+ if (const auto *PT = Pointee->getAs<PointerType>())
+ if (const auto *RT = PT->getPointeeType()->getAs<RecordType>())
+ if (S.isCFError(RT->getDecl()))
+ return true;
+
+ return false;
+}
+
+static void handleSwiftError(Sema &S, Decl *D, const ParsedAttr &AL) {
+ auto hasErrorParameter = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
+ for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); I != E; ++I) {
+ if (isErrorParameter(S, getFunctionOrMethodParamType(D, I)))
+ return true;
+ }
+
+ S.Diag(AL.getLoc(), diag::err_attr_swift_error_no_error_parameter)
+ << AL << isa<ObjCMethodDecl>(D);
+ return false;
+ };
+
+ auto hasPointerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
+ // - C, ObjC, and block pointers are definitely okay.
+ // - References are definitely not okay.
+ // - nullptr_t is weird, but acceptable.
+ QualType RT = getFunctionOrMethodResultType(D);
+ if (RT->hasPointerRepresentation() && !RT->isReferenceType())
+ return true;
+
+ S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)
+ << AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D)
+ << /*pointer*/ 1;
+ return false;
+ };
+
+ auto hasIntegerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
+ QualType RT = getFunctionOrMethodResultType(D);
+ if (RT->isIntegralType(S.Context))
+ return true;
+
+ S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)
+ << AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D)
+ << /*integral*/ 0;
+ return false;
+ };
+
+ if (D->isInvalidDecl())
+ return;
+
+ IdentifierLoc *Loc = AL.getArgAsIdent(0);
+ SwiftErrorAttr::ConventionKind Convention;
+ if (!SwiftErrorAttr::ConvertStrToConventionKind(Loc->Ident->getName(),
+ Convention)) {
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+ << AL << Loc->Ident;
+ return;
+ }
+
+ switch (Convention) {
+ case SwiftErrorAttr::None:
+ // No additional validation required.
+ break;
+
+ case SwiftErrorAttr::NonNullError:
+ if (!hasErrorParameter(S, D, AL))
+ return;
+ break;
+
+ case SwiftErrorAttr::NullResult:
+ if (!hasErrorParameter(S, D, AL) || !hasPointerResult(S, D, AL))
+ return;
+ break;
+
+ case SwiftErrorAttr::NonZeroResult:
+ case SwiftErrorAttr::ZeroResult:
+ if (!hasErrorParameter(S, D, AL) || !hasIntegerResult(S, D, AL))
+ return;
+ break;
+ }
+
+ D->addAttr(::new (S.Context) SwiftErrorAttr(S.Context, AL, Convention));
+}
+
+// For a function, this will validate a compound Swift name, e.g.
+// <code>init(foo:bar:baz:)</code> or <code>controllerForName(_:)</code>, and
+// the function will output the number of parameter names, and whether this is a
+// single-arg initializer.
+//
+// For a type, enum constant, property, or variable declaration, this will
+// validate either a simple identifier, or a qualified
+// <code>context.identifier</code> name.
+static bool
+validateSwiftFunctionName(Sema &S, const ParsedAttr &AL, SourceLocation Loc,
+ StringRef Name, unsigned &SwiftParamCount,
+ bool &IsSingleParamInit) {
+ SwiftParamCount = 0;
+ IsSingleParamInit = false;
+
+ // Check whether this will be mapped to a getter or setter of a property.
+ bool IsGetter = false, IsSetter = false;
+ if (Name.startswith("getter:")) {
+ IsGetter = true;
+ Name = Name.substr(7);
+ } else if (Name.startswith("setter:")) {
+ IsSetter = true;
+ Name = Name.substr(7);
+ }
+
+ if (Name.back() != ')') {
+ S.Diag(Loc, diag::warn_attr_swift_name_function) << AL;
+ return false;
+ }
+
+ bool IsMember = false;
+ StringRef ContextName, BaseName, Parameters;
+
+ std::tie(BaseName, Parameters) = Name.split('(');
+
+ // Split at the first '.', if it exists, which separates the context name
+ // from the base name.
+ std::tie(ContextName, BaseName) = BaseName.split('.');
+ if (BaseName.empty()) {
+ BaseName = ContextName;
+ ContextName = StringRef();
+ } else if (ContextName.empty() || !isValidIdentifier(ContextName)) {
+ S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
+ << AL << /*context*/ 1;
+ return false;
+ } else {
+ IsMember = true;
+ }
+
+ if (!isValidIdentifier(BaseName) || BaseName == "_") {
+ S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
+ << AL << /*basename*/ 0;
+ return false;
+ }
+
+ bool IsSubscript = BaseName == "subscript";
+ // A subscript accessor must be a getter or setter.
+ if (IsSubscript && !IsGetter && !IsSetter) {
+ S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
+ << AL << /* getter or setter */ 0;
+ return false;
+ }
+
+ if (Parameters.empty()) {
+ S.Diag(Loc, diag::warn_attr_swift_name_missing_parameters) << AL;
+ return false;
+ }
+
+ assert(Parameters.back() == ')' && "expected ')'");
+ Parameters = Parameters.drop_back(); // ')'
+
+ if (Parameters.empty()) {
+ // Setters and subscripts must have at least one parameter.
+ if (IsSubscript) {
+ S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
+ << AL << /* have at least one parameter */1;
+ return false;
+ }
+
+ if (IsSetter) {
+ S.Diag(Loc, diag::warn_attr_swift_name_setter_parameters) << AL;
+ return false;
+ }
+
+ return true;
+ }
+
+ if (Parameters.back() != ':') {
+ S.Diag(Loc, diag::warn_attr_swift_name_function) << AL;
+ return false;
+ }
+
+ StringRef CurrentParam;
+ llvm::Optional<unsigned> SelfLocation;
+ unsigned NewValueCount = 0;
+ llvm::Optional<unsigned> NewValueLocation;
+ do {
+ std::tie(CurrentParam, Parameters) = Parameters.split(':');
+
+ if (!isValidIdentifier(CurrentParam)) {
+ S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
+ << AL << /*parameter*/2;
+ return false;
+ }
+
+ if (IsMember && CurrentParam == "self") {
+ // "self" indicates the "self" argument for a member.
+
+ // More than one "self"?
+ if (SelfLocation) {
+ S.Diag(Loc, diag::warn_attr_swift_name_multiple_selfs) << AL;
+ return false;
+ }
+
+ // The "self" location is the current parameter.
+ SelfLocation = SwiftParamCount;
+ } else if (CurrentParam == "newValue") {
+ // "newValue" indicates the "newValue" argument for a setter.
+
+ // There should only be one 'newValue', but it's only significant for
+ // subscript accessors, so don't error right away.
+ ++NewValueCount;
+
+ NewValueLocation = SwiftParamCount;
+ }
+
+ ++SwiftParamCount;
+ } while (!Parameters.empty());
+
+ // Only instance subscripts are currently supported.
+ if (IsSubscript && !SelfLocation) {
+ S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
+ << AL << /*have a 'self:' parameter*/2;
+ return false;
+ }
+
+ IsSingleParamInit =
+ SwiftParamCount == 1 && BaseName == "init" && CurrentParam != "_";
+
+ // Check the number of parameters for a getter/setter.
+ if (IsGetter || IsSetter) {
+ // Setters have one parameter for the new value.
+ unsigned NumExpectedParams = IsGetter ? 0 : 1;
+ unsigned ParamDiag =
+ IsGetter ? diag::warn_attr_swift_name_getter_parameters
+ : diag::warn_attr_swift_name_setter_parameters;
+
+ // Instance methods have one parameter for "self".
+ if (SelfLocation)
+ ++NumExpectedParams;
+
+ // Subscripts may have additional parameters beyond the expected params for
+ // the index.
+ if (IsSubscript) {
+ if (SwiftParamCount < NumExpectedParams) {
+ S.Diag(Loc, ParamDiag) << AL;
+ return false;
+ }
+
+ // A subscript setter must explicitly label its newValue parameter to
+ // distinguish it from index parameters.
+ if (IsSetter) {
+ if (!NewValueLocation) {
+ S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_no_newValue)
+ << AL;
+ return false;
+ }
+ if (NewValueCount > 1) {
+ S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_multiple_newValues)
+ << AL;
+ return false;
+ }
+ } else {
+ // Subscript getters should have no 'newValue:' parameter.
+ if (NewValueLocation) {
+ S.Diag(Loc, diag::warn_attr_swift_name_subscript_getter_newValue)
+ << AL;
+ return false;
+ }
+ }
+ } else {
+ // Property accessors must have exactly the number of expected params.
+ if (SwiftParamCount != NumExpectedParams) {
+ S.Diag(Loc, ParamDiag) << AL;
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool Sema::DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc,
+ const ParsedAttr &AL, bool IsAsync) {
+ if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) {
+ ArrayRef<ParmVarDecl*> Params;
+ unsigned ParamCount;
+
+ if (const auto *Method = dyn_cast<ObjCMethodDecl>(D)) {
+ ParamCount = Method->getSelector().getNumArgs();
+ Params = Method->parameters().slice(0, ParamCount);
+ } else {
+ const auto *F = cast<FunctionDecl>(D);
+
+ ParamCount = F->getNumParams();
+ Params = F->parameters();
+
+ if (!F->hasWrittenPrototype()) {
+ Diag(Loc, diag::warn_attribute_wrong_decl_type) << AL
+ << ExpectedFunctionWithProtoType;
+ return false;
+ }
+ }
+
+ // The async name drops the last callback parameter.
+ if (IsAsync) {
+ if (ParamCount == 0) {
+ Diag(Loc, diag::warn_attr_swift_name_decl_missing_params)
+ << AL << isa<ObjCMethodDecl>(D);
+ return false;
+ }
+ ParamCount -= 1;
+ }
+
+ unsigned SwiftParamCount;
+ bool IsSingleParamInit;
+ if (!validateSwiftFunctionName(*this, AL, Loc, Name,
+ SwiftParamCount, IsSingleParamInit))
+ return false;
+
+ bool ParamCountValid;
+ if (SwiftParamCount == ParamCount) {
+ ParamCountValid = true;
+ } else if (SwiftParamCount > ParamCount) {
+ ParamCountValid = IsSingleParamInit && ParamCount == 0;
+ } else {
+ // We have fewer Swift parameters than Objective-C parameters, but that
+ // might be because we've transformed some of them. Check for potential
+ // "out" parameters and err on the side of not warning.
+ unsigned MaybeOutParamCount =
+ std::count_if(Params.begin(), Params.end(),
+ [](const ParmVarDecl *Param) -> bool {
+ QualType ParamTy = Param->getType();
+ if (ParamTy->isReferenceType() || ParamTy->isPointerType())
+ return !ParamTy->getPointeeType().isConstQualified();
+ return false;
+ });
+
+ ParamCountValid = SwiftParamCount + MaybeOutParamCount >= ParamCount;
+ }
+
+ if (!ParamCountValid) {
+ Diag(Loc, diag::warn_attr_swift_name_num_params)
+ << (SwiftParamCount > ParamCount) << AL << ParamCount
+ << SwiftParamCount;
+ return false;
+ }
+ } else if ((isa<EnumConstantDecl>(D) || isa<ObjCProtocolDecl>(D) ||
+ isa<ObjCInterfaceDecl>(D) || isa<ObjCPropertyDecl>(D) ||
+ isa<VarDecl>(D) || isa<TypedefNameDecl>(D) || isa<TagDecl>(D) ||
+ isa<IndirectFieldDecl>(D) || isa<FieldDecl>(D)) &&
+ !IsAsync) {
+ StringRef ContextName, BaseName;
+
+ std::tie(ContextName, BaseName) = Name.split('.');
+ if (BaseName.empty()) {
+ BaseName = ContextName;
+ ContextName = StringRef();
+ } else if (!isValidIdentifier(ContextName)) {
+ Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) << AL
+ << /*context*/1;
+ return false;
+ }
+
+ if (!isValidIdentifier(BaseName)) {
+ Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) << AL
+ << /*basename*/0;
+ return false;
+ }
+ } else {
+ Diag(Loc, diag::warn_attr_swift_name_decl_kind) << AL;
+ return false;
+ }
+ return true;
+}
+
+static void handleSwiftName(Sema &S, Decl *D, const ParsedAttr &AL) {
+ StringRef Name;
+ SourceLocation Loc;
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc))
+ return;
+
+ if (!S.DiagnoseSwiftName(D, Name, Loc, AL, /*IsAsync=*/false))
+ return;
+
+ D->addAttr(::new (S.Context) SwiftNameAttr(S.Context, AL, Name));
+}
+
+static void handleSwiftAsyncName(Sema &S, Decl *D, const ParsedAttr &AL) {
+ StringRef Name;
+ SourceLocation Loc;
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc))
+ return;
+
+ if (!S.DiagnoseSwiftName(D, Name, Loc, AL, /*IsAsync=*/true))
+ return;
+
+ D->addAttr(::new (S.Context) SwiftAsyncNameAttr(S.Context, AL, Name));
+}
+
+static void handleSwiftNewType(Sema &S, Decl *D, const ParsedAttr &AL) {
+ // Make sure that there is an identifier as the annotation's single argument.
+ if (!checkAttributeNumArgs(S, AL, 1))
+ return;
+
+ if (!AL.isArgIdent(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
+ << AL << AANT_ArgumentIdentifier;
+ return;
+ }
+
+ SwiftNewTypeAttr::NewtypeKind Kind;
+ IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
+ if (!SwiftNewTypeAttr::ConvertStrToNewtypeKind(II->getName(), Kind)) {
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
+ return;
+ }
+
+ if (!isa<TypedefNameDecl>(D)) {
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << AL << "typedefs";
+ return;
+ }
+
+ D->addAttr(::new (S.Context) SwiftNewTypeAttr(S.Context, AL, Kind));
+}
+
+static void handleSwiftAsyncAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!AL.isArgIdent(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL << 1 << AANT_ArgumentIdentifier;
+ return;
+ }
+
+ SwiftAsyncAttr::Kind Kind;
+ IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
+ if (!SwiftAsyncAttr::ConvertStrToKind(II->getName(), Kind)) {
+ S.Diag(AL.getLoc(), diag::err_swift_async_no_access) << AL << II;
+ return;
+ }
+
+ ParamIdx Idx;
+ if (Kind == SwiftAsyncAttr::None) {
+ // If this is 'none', then there shouldn't be any additional arguments.
+ if (!checkAttributeNumArgs(S, AL, 1))
+ return;
+ } else {
+ // Non-none swift_async requires a completion handler index argument.
+ if (!checkAttributeNumArgs(S, AL, 2))
+ return;
+
+ Expr *HandlerIdx = AL.getArgAsExpr(1);
+ if (!checkFunctionOrMethodParameterIndex(S, D, AL, 2, HandlerIdx, Idx))
+ return;
+
+ const ParmVarDecl *CompletionBlock =
+ getFunctionOrMethodParam(D, Idx.getASTIndex());
+ QualType CompletionBlockType = CompletionBlock->getType();
+ if (!CompletionBlockType->isBlockPointerType()) {
+ S.Diag(CompletionBlock->getLocation(),
+ diag::err_swift_async_bad_block_type)
+ << CompletionBlock->getType();
+ return;
+ }
+ QualType BlockTy =
+ CompletionBlockType->getAs<BlockPointerType>()->getPointeeType();
+ if (!BlockTy->getAs<FunctionType>()->getReturnType()->isVoidType()) {
+ S.Diag(CompletionBlock->getLocation(),
+ diag::err_swift_async_bad_block_type)
+ << CompletionBlock->getType();
+ return;
+ }
+ }
+
+ D->addAttr(::new (S.Context) SwiftAsyncAttr(S.Context, AL, Kind, Idx));
+}
+
//===----------------------------------------------------------------------===//
// Microsoft specific attribute handlers.
//===----------------------------------------------------------------------===//
@@ -5686,18 +6441,18 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
Expr *NumParamsExpr = static_cast<Expr *>(AL.getArgAsExpr(0));
- llvm::APSInt NumParams(32);
- if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
+ Optional<llvm::APSInt> NumParams = llvm::APSInt(32);
+ if (!(NumParams = NumParamsExpr->getIntegerConstantExpr(S.Context))) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
<< AL << AANT_ArgumentIntegerConstant
<< NumParamsExpr->getSourceRange();
return;
}
// The argument should be in range 0..63.
- unsigned Num = NumParams.getLimitedValue(255);
+ unsigned Num = NumParams->getLimitedValue(255);
if (Num > 63) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << AL << (int)NumParams.getSExtValue()
+ << AL << (int)NumParams->getSExtValue()
<< NumParamsExpr->getSourceRange();
return;
}
@@ -6246,14 +7001,14 @@ DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D,
static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) {
if (isa<ClassTemplatePartialSpecializationDecl>(D) &&
- S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ (S.Context.getTargetInfo().shouldDLLImportComdatSymbols())) {
S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored) << A;
return;
}
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isInlined() && A.getKind() == ParsedAttr::AT_DLLImport &&
- !S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ !(S.Context.getTargetInfo().shouldDLLImportComdatSymbols())) {
// MinGW doesn't allow dllimport on inline functions.
S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline)
<< A;
@@ -6262,7 +7017,7 @@ static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) {
}
if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
- if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ if ((S.Context.getTargetInfo().shouldDLLImportComdatSymbols()) &&
MD->getParent()->isLambda()) {
S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A;
return;
@@ -6788,6 +7543,75 @@ static void handleCFGuardAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
D->addAttr(::new (S.Context) CFGuardAttr(S.Context, AL, Arg));
}
+
+template <typename AttrTy>
+static const AttrTy *findEnforceTCBAttrByName(Decl *D, StringRef Name) {
+ auto Attrs = D->specific_attrs<AttrTy>();
+ auto I = llvm::find_if(Attrs,
+ [Name](const AttrTy *A) {
+ return A->getTCBName() == Name;
+ });
+ return I == Attrs.end() ? nullptr : *I;
+}
+
+template <typename AttrTy, typename ConflictingAttrTy>
+static void handleEnforceTCBAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ StringRef Argument;
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Argument))
+ return;
+
+ // A function cannot be have both regular and leaf membership in the same TCB.
+ if (const ConflictingAttrTy *ConflictingAttr =
+ findEnforceTCBAttrByName<ConflictingAttrTy>(D, Argument)) {
+ // We could attach a note to the other attribute but in this case
+ // there's no need given how the two are very close to each other.
+ S.Diag(AL.getLoc(), diag::err_tcb_conflicting_attributes)
+ << AL.getAttrName()->getName() << ConflictingAttr->getAttrName()->getName()
+ << Argument;
+
+ // Error recovery: drop the non-leaf attribute so that to suppress
+ // all future warnings caused by erroneous attributes. The leaf attribute
+ // needs to be kept because it can only suppresses warnings, not cause them.
+ D->dropAttr<EnforceTCBAttr>();
+ return;
+ }
+
+ D->addAttr(AttrTy::Create(S.Context, Argument, AL));
+}
+
+template <typename AttrTy, typename ConflictingAttrTy>
+static AttrTy *mergeEnforceTCBAttrImpl(Sema &S, Decl *D, const AttrTy &AL) {
+ // Check if the new redeclaration has different leaf-ness in the same TCB.
+ StringRef TCBName = AL.getTCBName();
+ if (const ConflictingAttrTy *ConflictingAttr =
+ findEnforceTCBAttrByName<ConflictingAttrTy>(D, TCBName)) {
+ S.Diag(ConflictingAttr->getLoc(), diag::err_tcb_conflicting_attributes)
+ << ConflictingAttr->getAttrName()->getName()
+ << AL.getAttrName()->getName() << TCBName;
+
+ // Add a note so that the user could easily find the conflicting attribute.
+ S.Diag(AL.getLoc(), diag::note_conflicting_attribute);
+
+ // More error recovery.
+ D->dropAttr<EnforceTCBAttr>();
+ return nullptr;
+ }
+
+ ASTContext &Context = S.getASTContext();
+ return ::new(Context) AttrTy(Context, AL, AL.getTCBName());
+}
+
+EnforceTCBAttr *Sema::mergeEnforceTCBAttr(Decl *D, const EnforceTCBAttr &AL) {
+ return mergeEnforceTCBAttrImpl<EnforceTCBAttr, EnforceTCBLeafAttr>(
+ *this, D, AL);
+}
+
+EnforceTCBLeafAttr *Sema::mergeEnforceTCBLeafAttr(
+ Decl *D, const EnforceTCBLeafAttr &AL) {
+ return mergeEnforceTCBAttrImpl<EnforceTCBLeafAttr, EnforceTCBAttr>(
+ *this, D, AL);
+}
+
//===----------------------------------------------------------------------===//
// Top Level Sema Entry Points
//===----------------------------------------------------------------------===//
@@ -6815,7 +7639,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
AL.isDeclspecAttribute()
? (unsigned)diag::warn_unhandled_ms_attribute_ignored
: (unsigned)diag::warn_unknown_attribute_ignored)
- << AL;
+ << AL << AL.getRange();
return;
}
@@ -6939,19 +7763,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handlePassObjectSizeAttr(S, D, AL);
break;
case ParsedAttr::AT_Constructor:
- if (S.Context.getTargetInfo().getTriple().isOSAIX())
- llvm::report_fatal_error(
- "'constructor' attribute is not yet supported on AIX");
- else
handleConstructorAttr(S, D, AL);
break;
case ParsedAttr::AT_Deprecated:
handleDeprecatedAttr(S, D, AL);
break;
case ParsedAttr::AT_Destructor:
- if (S.Context.getTargetInfo().getTriple().isOSAIX())
- llvm::report_fatal_error("'destructor' attribute is not yet supported on AIX");
- else
handleDestructorAttr(S, D, AL);
break;
case ParsedAttr::AT_EnableIf:
@@ -6990,16 +7807,21 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_Callback:
handleCallbackAttr(S, D, AL);
break;
+ case ParsedAttr::AT_CalledOnce:
+ handleCalledOnceAttr(S, D, AL);
+ break;
case ParsedAttr::AT_CUDAGlobal:
handleGlobalAttr(S, D, AL);
break;
case ParsedAttr::AT_CUDADevice:
- handleSimpleAttributeWithExclusions<CUDADeviceAttr, CUDAGlobalAttr>(S, D,
- AL);
+ handleDeviceAttr(S, D, AL);
break;
case ParsedAttr::AT_CUDAHost:
handleSimpleAttributeWithExclusions<CUDAHostAttr, CUDAGlobalAttr>(S, D, AL);
break;
+ case ParsedAttr::AT_HIPManaged:
+ handleManagedAttr(S, D, AL);
+ break;
case ParsedAttr::AT_CUDADeviceBuiltinSurfaceType:
handleSimpleAttributeWithExclusions<CUDADeviceBuiltinSurfaceTypeAttr,
CUDADeviceBuiltinTextureTypeAttr>(S, D,
@@ -7058,6 +7880,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_AnyX86NoCfCheck:
handleNoCfCheckAttr(S, D, AL);
break;
+ case ParsedAttr::AT_Leaf:
+ handleSimpleAttribute<LeafAttr>(S, D, AL);
+ break;
case ParsedAttr::AT_NoThrow:
if (!AL.isUsedAsTypeAttr())
handleSimpleAttribute<NoThrowAttr>(S, D, AL);
@@ -7098,6 +7923,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_ObjCBoxable:
handleObjCBoxable(S, D, AL);
break;
+ case ParsedAttr::AT_NSErrorDomain:
+ handleNSErrorDomain(S, D, AL);
+ break;
case ParsedAttr::AT_CFAuditedTransfer:
handleSimpleAttributeWithExclusions<CFAuditedTransferAttr,
CFUnknownTransferAttr>(S, D, AL);
@@ -7155,6 +7983,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_Packed:
handlePackedAttr(S, D, AL);
break;
+ case ParsedAttr::AT_PreferredName:
+ handlePreferredName(S, D, AL);
+ break;
case ParsedAttr::AT_Section:
handleSectionAttr(S, D, AL);
break;
@@ -7179,9 +8010,15 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_Unavailable:
handleAttrWithMessage<UnavailableAttr>(S, D, AL);
break;
+ case ParsedAttr::AT_Assumption:
+ handleAssumumptionAttr(S, D, AL);
+ break;
case ParsedAttr::AT_ObjCDirect:
handleObjCDirectAttr(S, D, AL);
break;
+ case ParsedAttr::AT_ObjCNonRuntimeProtocol:
+ handleObjCNonRuntimeProtocolAttr(S, D, AL);
+ break;
case ParsedAttr::AT_ObjCDirectMembers:
handleObjCDirectMembersAttr(S, D, AL);
handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL);
@@ -7200,6 +8037,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleSimpleAttributeWithExclusions<DisableTailCallsAttr, NakedAttr>(S, D,
AL);
break;
+ case ParsedAttr::AT_NoMerge:
+ handleSimpleAttribute<NoMergeAttr>(S, D, AL);
+ break;
case ParsedAttr::AT_Visibility:
handleVisibilityAttr(S, D, AL, false);
break;
@@ -7397,6 +8237,38 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleTypeTagForDatatypeAttr(S, D, AL);
break;
+ // Swift attributes.
+ case ParsedAttr::AT_SwiftAsyncName:
+ handleSwiftAsyncName(S, D, AL);
+ break;
+ case ParsedAttr::AT_SwiftAttr:
+ handleSwiftAttrAttr(S, D, AL);
+ break;
+ case ParsedAttr::AT_SwiftBridge:
+ handleSwiftBridge(S, D, AL);
+ break;
+ case ParsedAttr::AT_SwiftBridgedTypedef:
+ handleSimpleAttribute<SwiftBridgedTypedefAttr>(S, D, AL);
+ break;
+ case ParsedAttr::AT_SwiftError:
+ handleSwiftError(S, D, AL);
+ break;
+ case ParsedAttr::AT_SwiftName:
+ handleSwiftName(S, D, AL);
+ break;
+ case ParsedAttr::AT_SwiftNewType:
+ handleSwiftNewType(S, D, AL);
+ break;
+ case ParsedAttr::AT_SwiftObjCMembers:
+ handleSimpleAttribute<SwiftObjCMembersAttr>(S, D, AL);
+ break;
+ case ParsedAttr::AT_SwiftPrivate:
+ handleSimpleAttribute<SwiftPrivateAttr>(S, D, AL);
+ break;
+ case ParsedAttr::AT_SwiftAsync:
+ handleSwiftAsyncAttr(S, D, AL);
+ break;
+
// XRay attributes.
case ParsedAttr::AT_XRayLogArgs:
handleXRayLogArgsAttr(S, D, AL);
@@ -7446,6 +8318,14 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_UseHandle:
handleHandleAttr<UseHandleAttr>(S, D, AL);
break;
+
+ case ParsedAttr::AT_EnforceTCB:
+ handleEnforceTCBAttr<EnforceTCBAttr, EnforceTCBLeafAttr>(S, D, AL);
+ break;
+
+ case ParsedAttr::AT_EnforceTCBLeaf:
+ handleEnforceTCBAttr<EnforceTCBLeafAttr, EnforceTCBAttr>(S, D, AL);
+ break;
}
}
@@ -7600,8 +8480,8 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
NewFD = FunctionDecl::Create(
FD->getASTContext(), FD->getDeclContext(), Loc, Loc,
DeclarationName(II), FD->getType(), FD->getTypeSourceInfo(), SC_None,
- false /*isInlineSpecified*/, FD->hasPrototype(), CSK_unspecified,
- FD->getTrailingRequiresClause());
+ false /*isInlineSpecified*/, FD->hasPrototype(),
+ ConstexprSpecKind::Unspecified, FD->getTrailingRequiresClause());
NewD = NewFD;
if (FD->getQualifier())
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 22bf35dbd0cb..8bfaa46162bc 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -655,7 +655,8 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
// contain the constexpr specifier.
if (New->getConstexprKind() != Old->getConstexprKind()) {
Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch)
- << New << New->getConstexprKind() << Old->getConstexprKind();
+ << New << static_cast<int>(New->getConstexprKind())
+ << static_cast<int>(Old->getConstexprKind());
Diag(Old->getLocation(), diag::note_previous_declaration);
Invalid = true;
} else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() &&
@@ -694,6 +695,17 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
Invalid = true;
}
+ // C++11 [temp.friend]p4 (DR329):
+ // When a function is defined in a friend function declaration in a class
+ // template, the function is instantiated when the function is odr-used.
+ // The same restrictions on multiple declarations and definitions that
+ // apply to non-template function declarations and definitions also apply
+ // to these implicit definitions.
+ const FunctionDecl *OldDefinition = nullptr;
+ if (New->isThisDeclarationInstantiatedFromAFriendDefinition() &&
+ Old->isDefined(OldDefinition, true))
+ CheckForFunctionRedefinition(New, OldDefinition);
+
return Invalid;
}
@@ -723,7 +735,7 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
Diag(Decomp.getLSquareLoc(),
!getLangOpts().CPlusPlus17
? diag::ext_decomp_decl
- : D.getContext() == DeclaratorContext::ConditionContext
+ : D.getContext() == DeclaratorContext::Condition
? diag::ext_decomp_decl_cond
: diag::warn_cxx14_compat_decomp_decl)
<< Decomp.getSourceRange();
@@ -890,7 +902,8 @@ static bool checkSimpleDecomposition(
llvm::function_ref<ExprResult(SourceLocation, Expr *, unsigned)> GetInit) {
if ((int64_t)Bindings.size() != NumElems) {
S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
- << DecompType << (unsigned)Bindings.size() << NumElems.toString(10)
+ << DecompType << (unsigned)Bindings.size()
+ << (unsigned)NumElems.getLimitedValue(UINT_MAX) << NumElems.toString(10)
<< (NumElems < Bindings.size());
return true;
}
@@ -1066,8 +1079,9 @@ static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T,
TemplateArgumentListInfo &Args;
ICEDiagnoser(LookupResult &R, TemplateArgumentListInfo &Args)
: R(R), Args(Args) {}
- void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override {
- S.Diag(Loc, diag::err_decomp_decl_std_tuple_size_not_constant)
+ Sema::SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
+ SourceLocation Loc) override {
+ return S.Diag(Loc, diag::err_decomp_decl_std_tuple_size_not_constant)
<< printTemplateArgs(S.Context.getPrintingPolicy(), Args);
}
} Diagnoser(R, Args);
@@ -1077,7 +1091,7 @@ static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T,
if (E.isInvalid())
return IsTupleLike::Error;
- E = S.VerifyIntegerConstantExpression(E.get(), &Size, Diagnoser, false);
+ E = S.VerifyIntegerConstantExpression(E.get(), &Size, Diagnoser);
if (E.isInvalid())
return IsTupleLike::Error;
@@ -1135,8 +1149,9 @@ static bool checkTupleLikeDecomposition(Sema &S,
const llvm::APSInt &TupleSize) {
if ((int64_t)Bindings.size() != TupleSize) {
S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
- << DecompType << (unsigned)Bindings.size() << TupleSize.toString(10)
- << (TupleSize < Bindings.size());
+ << DecompType << (unsigned)Bindings.size()
+ << (unsigned)TupleSize.getLimitedValue(UINT_MAX)
+ << TupleSize.toString(10) << (TupleSize < Bindings.size());
return true;
}
@@ -1184,7 +1199,8 @@ static bool checkTupleLikeDecomposition(Sema &S,
// an xvalue otherwise
if (!Src->getType()->isLValueReferenceType())
E = ImplicitCastExpr::Create(S.Context, E.get()->getType(), CK_NoOp,
- E.get(), nullptr, VK_XValue);
+ E.get(), nullptr, VK_XValue,
+ FPOptionsOverride());
TemplateArgumentListInfo Args(Loc, Loc);
Args.addArgument(
@@ -1248,8 +1264,7 @@ static bool checkTupleLikeDecomposition(Sema &S,
if (E.isInvalid())
return true;
RefVD->setInit(E.get());
- if (!E.get()->isValueDependent())
- RefVD->checkInitIsICE();
+ S.CheckCompleteVariableDeclaration(RefVD);
E = S.BuildDeclarationNameExpr(CXXScopeSpec(),
DeclarationNameInfo(B->getDeclName(), Loc),
@@ -1360,7 +1375,7 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
[](FieldDecl *FD) { return !FD->isUnnamedBitfield(); });
assert(Bindings.size() != NumFields);
S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
- << DecompType << (unsigned)Bindings.size() << NumFields
+ << DecompType << (unsigned)Bindings.size() << NumFields << NumFields
<< (NumFields < Bindings.size());
return true;
};
@@ -1373,11 +1388,23 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
if (FD->isUnnamedBitfield())
continue;
- if (FD->isAnonymousStructOrUnion()) {
- S.Diag(Src->getLocation(), diag::err_decomp_decl_anon_union_member)
- << DecompType << FD->getType()->isUnionType();
- S.Diag(FD->getLocation(), diag::note_declared_at);
- return true;
+ // All the non-static data members are required to be nameable, so they
+ // must all have names.
+ if (!FD->getDeclName()) {
+ if (RD->isLambda()) {
+ S.Diag(Src->getLocation(), diag::err_decomp_decl_lambda);
+ S.Diag(RD->getLocation(), diag::note_lambda_decl);
+ return true;
+ }
+
+ if (FD->isAnonymousStructOrUnion()) {
+ S.Diag(Src->getLocation(), diag::err_decomp_decl_anon_union_member)
+ << DecompType << FD->getType()->isUnionType();
+ S.Diag(FD->getLocation(), diag::note_declared_at);
+ return true;
+ }
+
+ // FIXME: Are there any other ways we could have an anonymous member?
}
// We have a real field to bind.
@@ -1618,7 +1645,7 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
if (Kind == Sema::CheckConstexprKind::Diagnose) {
SemaRef.Diag(DD->getLocation(), diag::err_constexpr_dtor_subobject)
- << DD->getConstexprKind() << !FD
+ << static_cast<int>(DD->getConstexprKind()) << !FD
<< (FD ? FD->getDeclName() : DeclarationName()) << T;
SemaRef.Diag(Loc, diag::note_constexpr_dtor_subobject)
<< !FD << (FD ? FD->getDeclName() : DeclarationName()) << T;
@@ -2588,7 +2615,7 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
Diag(AL.getLoc(), AL.getKind() == ParsedAttr::UnknownAttribute
? (unsigned)diag::warn_unknown_attribute_ignored
: (unsigned)diag::err_base_specifier_attribute)
- << AL;
+ << AL << AL.getRange();
}
TypeSourceInfo *TInfo = nullptr;
@@ -3577,8 +3604,10 @@ namespace {
Base = SubME->getBase();
}
- if (!isa<CXXThisExpr>(Base->IgnoreParenImpCasts()))
+ if (!isa<CXXThisExpr>(Base->IgnoreParenImpCasts())) {
+ Visit(Base);
return;
+ }
if (AddressOf && AllPODFields)
return;
@@ -3905,9 +3934,22 @@ void Sema::ActOnStartTrailingRequiresClause(Scope *S, Declarator &D) {
}
ExprResult Sema::ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr) {
+ return ActOnRequiresClause(ConstraintExpr);
+}
+
+ExprResult Sema::ActOnRequiresClause(ExprResult ConstraintExpr) {
+ if (ConstraintExpr.isInvalid())
+ return ExprError();
+
+ ConstraintExpr = CorrectDelayedTyposInExpr(ConstraintExpr);
if (ConstraintExpr.isInvalid())
return ExprError();
- return CorrectDelayedTyposInExpr(ConstraintExpr);
+
+ if (DiagnoseUnexpandedParameterPack(ConstraintExpr.get(),
+ UPPC_RequiresClause))
+ return ExprError();
+
+ return ConstraintExpr;
}
/// This is invoked after parsing an in-class initializer for a
@@ -5478,8 +5520,9 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
// Bases.
for (const auto &Base : ClassDecl->bases()) {
- // Bases are always records in a well-formed non-dependent class.
const RecordType *RT = Base.getType()->getAs<RecordType>();
+ if (!RT)
+ continue;
// Remember direct virtual bases.
if (Base.isVirtual()) {
@@ -5869,13 +5912,22 @@ static void ReferenceDllExportedMembers(Sema &S, CXXRecordDecl *Class) {
// The function will be passed to the consumer when its definition is
// encountered.
- } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() ||
+ } else if (MD->isExplicitlyDefaulted()) {
+ // Synthesize and instantiate explicitly defaulted methods.
+ S.MarkFunctionReferenced(Class->getLocation(), MD);
+
+ if (TSK != TSK_ExplicitInstantiationDefinition) {
+ // Except for explicit instantiation defs, we will not see the
+ // definition again later, so pass it to the consumer now.
+ S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD));
+ }
+ } else if (!MD->isTrivial() ||
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 across libraries.
+ // Synthesize and instantiate non-trivial implicit 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 across libraries.
S.MarkFunctionReferenced(Class->getLocation(), MD);
// There is no later point when we will see the definition of this
@@ -6056,7 +6108,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
Attr *ClassAttr = getDLLAttr(Class);
// MSVC inherits DLL attributes to partial class template specializations.
- if (Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) {
+ if (Context.getTargetInfo().shouldDLLImportComdatSymbols() && !ClassAttr) {
if (auto *Spec = dyn_cast<ClassTemplatePartialSpecializationDecl>(Class)) {
if (Attr *TemplateAttr =
getDLLAttr(Spec->getSpecializedTemplate()->getTemplatedDecl())) {
@@ -6076,7 +6128,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
return;
}
- if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ if (Context.getTargetInfo().shouldDLLImportComdatSymbols() &&
!ClassAttr->isInherited()) {
// Diagnose dll attributes on members of class with dll attribute.
for (Decl *Member : Class->decls()) {
@@ -6141,8 +6193,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
if (MD->isInlined()) {
// MinGW does not import or export inline methods. But do it for
// template instantiations.
- if (!Context.getTargetInfo().getCXXABI().isMicrosoft() &&
- !Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment() &&
+ if (!Context.getTargetInfo().shouldDLLImportComdatSymbols() &&
TSK != TSK_ExplicitInstantiationDeclaration &&
TSK != TSK_ExplicitInstantiationDefinition)
continue;
@@ -7331,9 +7382,10 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
// If a function is explicitly defaulted on its first declaration, it is
// implicitly considered to be constexpr if the implicit declaration
// would be.
- MD->setConstexprKind(
- Constexpr ? (MD->isConsteval() ? CSK_consteval : CSK_constexpr)
- : CSK_unspecified);
+ MD->setConstexprKind(Constexpr ? (MD->isConsteval()
+ ? ConstexprSpecKind::Consteval
+ : ConstexprSpecKind::Constexpr)
+ : ConstexprSpecKind::Unspecified);
if (!Type->hasExceptionSpec()) {
// C++2a [except.spec]p3:
@@ -8022,10 +8074,10 @@ private:
if (ReturnFalse.isInvalid())
return StmtError();
- return S.ActOnIfStmt(Loc, false, nullptr,
+ return S.ActOnIfStmt(Loc, false, Loc, nullptr,
S.ActOnCondition(nullptr, Loc, NotCond.get(),
Sema::ConditionKind::Boolean),
- ReturnFalse.get(), SourceLocation(), nullptr);
+ Loc, ReturnFalse.get(), SourceLocation(), nullptr);
}
StmtResult visitSubobjectArray(QualType Type, llvm::APInt Size,
@@ -8177,9 +8229,9 @@ private:
return StmtError();
// if (...)
- return S.ActOnIfStmt(Loc, /*IsConstexpr=*/false, InitStmt, Cond,
- ReturnStmt.get(), /*ElseLoc=*/SourceLocation(),
- /*Else=*/nullptr);
+ return S.ActOnIfStmt(Loc, /*IsConstexpr=*/false, Loc, InitStmt, Cond, Loc,
+ ReturnStmt.get(),
+ /*ElseLoc=*/SourceLocation(), /*Else=*/nullptr);
}
case DefaultedComparisonKind::NotEqual:
@@ -8212,7 +8264,7 @@ static void lookupOperatorsForDefaultedComparison(Sema &Self, Scope *S,
UnresolvedSetImpl &Operators,
OverloadedOperatorKind Op) {
auto Lookup = [&](OverloadedOperatorKind OO) {
- Self.LookupOverloadedOperatorName(OO, S, QualType(), QualType(), Operators);
+ Self.LookupOverloadedOperatorName(OO, S, Operators);
};
// Every defaulted operator looks up itself.
@@ -8425,7 +8477,7 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
// FIXME: Only applying this to the first declaration seems problematic, as
// simple reorderings can affect the meaning of the program.
if (First && !FD->isConstexpr() && Info.Constexpr)
- FD->setConstexprKind(CSK_constexpr);
+ FD->setConstexprKind(ConstexprSpecKind::Constexpr);
// C++2a [except.spec]p3:
// If a declaration of a function does not have a noexcept-specifier
@@ -9399,7 +9451,8 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
// brace-or-equal-initializer
if (CSM == Sema::CXXDefaultConstructor && FI->hasInClassInitializer()) {
if (Diagnose)
- S.Diag(FI->getLocation(), diag::note_nontrivial_in_class_init) << FI;
+ S.Diag(FI->getLocation(), diag::note_nontrivial_default_member_init)
+ << FI;
return false;
}
@@ -11106,8 +11159,8 @@ QualType Sema::CheckComparisonCategoryType(ComparisonCategoryType Kind,
// Attempt to diagnose reasons why the STL definition of this type
// might be foobar, including it failing to be a constant expression.
// TODO Handle more ways the lookup or result can be invalid.
- if (!VD->isStaticDataMember() || !VD->isConstexpr() || !VD->hasInit() ||
- !VD->checkInitIsICE())
+ if (!VD->isStaticDataMember() ||
+ !VD->isUsableInConstantExpressions(Context))
return UnsupportedSTLError(USS_InvalidMember, MemName, VD);
// Attempt to evaluate the var decl as a constant expression and extract
@@ -12936,7 +12989,8 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
Context, ClassDecl, ClassLoc, NameInfo, /*Type*/ QualType(),
/*TInfo=*/nullptr, ExplicitSpecifier(),
/*isInline=*/true, /*isImplicitlyDeclared=*/true,
- Constexpr ? CSK_constexpr : CSK_unspecified);
+ Constexpr ? ConstexprSpecKind::Constexpr
+ : ConstexprSpecKind::Unspecified);
DefaultCon->setAccess(AS_public);
DefaultCon->setDefaulted();
@@ -13057,7 +13111,7 @@ Sema::findInheritingConstructor(SourceLocation Loc,
Context, Derived, UsingLoc, NameInfo, TInfo->getType(), TInfo,
BaseCtor->getExplicitSpecifier(), /*isInline=*/true,
/*isImplicitlyDeclared=*/true,
- Constexpr ? BaseCtor->getConstexprKind() : CSK_unspecified,
+ Constexpr ? BaseCtor->getConstexprKind() : ConstexprSpecKind::Unspecified,
InheritedConstructor(Shadow, BaseCtor),
BaseCtor->getTrailingRequiresClause());
if (Shadow->isInvalidDecl())
@@ -13214,7 +13268,8 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,
QualType(), nullptr, /*isInline=*/true,
/*isImplicitlyDeclared=*/true,
- Constexpr ? CSK_constexpr : CSK_unspecified);
+ Constexpr ? ConstexprSpecKind::Constexpr
+ : ConstexprSpecKind::Unspecified);
Destructor->setAccess(AS_public);
Destructor->setDefaulted();
@@ -13849,7 +13904,8 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
CXXMethodDecl *CopyAssignment = CXXMethodDecl::Create(
Context, ClassDecl, ClassLoc, NameInfo, QualType(),
/*TInfo=*/nullptr, /*StorageClass=*/SC_None,
- /*isInline=*/true, Constexpr ? CSK_constexpr : CSK_unspecified,
+ /*isInline=*/true,
+ Constexpr ? ConstexprSpecKind::Constexpr : ConstexprSpecKind::Unspecified,
SourceLocation());
CopyAssignment->setAccess(AS_public);
CopyAssignment->setDefaulted();
@@ -14174,7 +14230,8 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
CXXMethodDecl *MoveAssignment = CXXMethodDecl::Create(
Context, ClassDecl, ClassLoc, NameInfo, QualType(),
/*TInfo=*/nullptr, /*StorageClass=*/SC_None,
- /*isInline=*/true, Constexpr ? CSK_constexpr : CSK_unspecified,
+ /*isInline=*/true,
+ Constexpr ? ConstexprSpecKind::Constexpr : ConstexprSpecKind::Unspecified,
SourceLocation());
MoveAssignment->setAccess(AS_public);
MoveAssignment->setDefaulted();
@@ -14558,7 +14615,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
ExplicitSpecifier(),
/*isInline=*/true,
/*isImplicitlyDeclared=*/true,
- Constexpr ? CSK_constexpr : CSK_unspecified);
+ Constexpr ? ConstexprSpecKind::Constexpr
+ : ConstexprSpecKind::Unspecified);
CopyConstructor->setAccess(AS_public);
CopyConstructor->setDefaulted();
@@ -14691,7 +14749,8 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
ExplicitSpecifier(),
/*isInline=*/true,
/*isImplicitlyDeclared=*/true,
- Constexpr ? CSK_constexpr : CSK_unspecified);
+ Constexpr ? ConstexprSpecKind::Constexpr
+ : ConstexprSpecKind::Unspecified);
MoveConstructor->setAccess(AS_public);
MoveConstructor->setDefaulted();
@@ -14793,9 +14852,13 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
SynthesizedFunctionScope Scope(*this, Conv);
assert(!Conv->getReturnType()->isUndeducedType());
+ QualType ConvRT = Conv->getType()->getAs<FunctionType>()->getReturnType();
+ CallingConv CC =
+ ConvRT->getPointeeType()->getAs<FunctionType>()->getCallConv();
+
CXXRecordDecl *Lambda = Conv->getParent();
FunctionDecl *CallOp = Lambda->getLambdaCallOperator();
- FunctionDecl *Invoker = Lambda->getLambdaStaticInvoker();
+ FunctionDecl *Invoker = Lambda->getLambdaStaticInvoker(CC);
if (auto *TemplateArgs = Conv->getTemplateSpecializationArgs()) {
CallOp = InstantiateFunctionDeclaration(
@@ -14866,9 +14929,9 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
// (since it's unusable otherwise); in the case where we inline the
// block literal, it has block literal lifetime semantics.
if (!BuildBlock.isInvalid() && !getLangOpts().ObjCAutoRefCount)
- BuildBlock = ImplicitCastExpr::Create(Context, BuildBlock.get()->getType(),
- CK_CopyAndAutoreleaseBlockObject,
- BuildBlock.get(), nullptr, VK_RValue);
+ BuildBlock = ImplicitCastExpr::Create(
+ Context, BuildBlock.get()->getType(), CK_CopyAndAutoreleaseBlockObject,
+ BuildBlock.get(), nullptr, VK_RValue, FPOptionsOverride());
if (BuildBlock.isInvalid()) {
Diag(CurrentLocation, diag::note_lambda_to_block_conv);
@@ -15032,24 +15095,14 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
DeclContext::lookup_result Lookup =
ClassPattern->lookup(Field->getDeclName());
- // Lookup can return at most two results: the pattern for the field, or the
- // injected class name of the parent record. No other member can have the
- // same name as the field.
- // In modules mode, lookup can return multiple results (coming from
- // different modules).
- assert((getLangOpts().Modules || (!Lookup.empty() && Lookup.size() <= 2)) &&
- "more than two lookup results for field name");
- FieldDecl *Pattern = dyn_cast<FieldDecl>(Lookup[0]);
- if (!Pattern) {
- assert(isa<CXXRecordDecl>(Lookup[0]) &&
- "cannot have other non-field member with same name");
- for (auto L : Lookup)
- if (isa<FieldDecl>(L)) {
- Pattern = cast<FieldDecl>(L);
- break;
- }
- assert(Pattern && "We must have set the Pattern!");
+ FieldDecl *Pattern = nullptr;
+ for (auto L : Lookup) {
+ if (isa<FieldDecl>(L)) {
+ Pattern = cast<FieldDecl>(L);
+ break;
+ }
}
+ assert(Pattern && "We must have set the Pattern!");
if (!Pattern->hasInClassInitializer() ||
InstantiateInClassInitializer(Loc, Field, Pattern,
@@ -15076,9 +15129,10 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
// constructor before the initializer is lexically complete will ultimately
// come here at which point we can diagnose it.
RecordDecl *OutermostClass = ParentRD->getOuterLexicalRecordContext();
- Diag(Loc, diag::err_in_class_initializer_not_yet_parsed)
+ Diag(Loc, diag::err_default_member_initializer_not_yet_parsed)
<< OutermostClass << Field;
- Diag(Field->getEndLoc(), diag::note_in_class_initializer_not_yet_parsed);
+ Diag(Field->getEndLoc(),
+ diag::note_default_member_initializer_not_yet_parsed);
// Recover by marking the field invalid, unless we're in a SFINAE context.
if (!isSFINAEContext())
Field->setInvalidDecl();
@@ -15503,6 +15557,18 @@ checkLiteralOperatorTemplateParameterList(Sema &SemaRef,
SemaRef.Context.hasSameType(PmDecl->getType(), SemaRef.Context.CharTy))
return false;
+ // C++20 [over.literal]p5:
+ // A string literal operator template is a literal operator template
+ // whose template-parameter-list comprises a single non-type
+ // template-parameter of class type.
+ //
+ // As a DR resolution, we also allow placeholders for deduced class
+ // template specializations.
+ if (SemaRef.getLangOpts().CPlusPlus20 &&
+ !PmDecl->isTemplateParameterPack() &&
+ (PmDecl->getType()->isRecordType() ||
+ PmDecl->getType()->getAs<DeducedTemplateSpecializationType>()))
+ return false;
} else if (TemplateParams->size() == 2) {
TemplateTypeParmDecl *PmType =
dyn_cast<TemplateTypeParmDecl>(TemplateParams->getParam(0));
@@ -15559,6 +15625,8 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
// template <char...> type operator "" name() and
// template <class T, T...> type operator "" name() are the only valid
// template signatures, and the only valid signatures with no parameters.
+ //
+ // C++20 also allows template <SomeClass T> type operator "" name().
if (TpDecl) {
if (FnDecl->param_size() != 0) {
Diag(FnDecl->getLocation(),
@@ -15988,9 +16056,10 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
AssertExpr = FullAssertExpr.get();
llvm::APSInt Cond;
- if (!Failed && VerifyIntegerConstantExpression(AssertExpr, &Cond,
- diag::err_static_assert_expression_is_not_constant,
- /*AllowFold=*/false).isInvalid())
+ if (!Failed && VerifyIntegerConstantExpression(
+ AssertExpr, &Cond,
+ diag::err_static_assert_expression_is_not_constant)
+ .isInvalid())
Failed = true;
if (!Failed && !Cond) {
@@ -16282,7 +16351,7 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
// Try to convert the decl specifier to a type. This works for
// friend templates because ActOnTag never produces a ClassTemplateDecl
// for a TUK_Friend.
- Declarator TheDeclarator(DS, DeclaratorContext::MemberContext);
+ Declarator TheDeclarator(DS, DeclaratorContext::Member);
TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S);
QualType T = TSI->getType();
if (TheDeclarator.isInvalidType())
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index d376880a40e8..60253a82e93a 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -1066,6 +1066,11 @@ Decl *Sema::ActOnStartClassInterface(
ProcessDeclAttributeList(TUScope, IDecl, AttrList);
AddPragmaAttributes(TUScope, IDecl);
+
+ // Merge attributes from previous declarations.
+ if (PrevIDecl)
+ mergeDeclAttributes(IDecl, PrevIDecl);
+
PushOnScopeChains(IDecl, TUScope);
// Start the definition of this class. If we're in a redefinition case, there
@@ -1581,7 +1586,7 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers(
DS.SetRangeEnd(loc);
// Form the declarator.
- Declarator D(DS, DeclaratorContext::TypeNameContext);
+ Declarator D(DS, DeclaratorContext::TypeName);
// If we have a typedef of an Objective-C class type that is missing a '*',
// add the '*'.
@@ -2122,7 +2127,12 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
// Add ivar's to class's DeclContext.
for (unsigned i = 0, e = numIvars; i != e; ++i) {
ivars[i]->setLexicalDeclContext(ImpDecl);
- IDecl->makeDeclVisibleInContext(ivars[i]);
+ // In a 'fragile' runtime the ivar was added to the implicit
+ // ObjCInterfaceDecl while in a 'non-fragile' runtime the ivar is
+ // only in the ObjCImplementationDecl. In the non-fragile case the ivar
+ // therefore also needs to be propagated to the ObjCInterfaceDecl.
+ if (!LangOpts.ObjCRuntime.isFragile())
+ IDecl->makeDeclVisibleInContext(ivars[i]);
ImpDecl->addDecl(ivars[i]);
}
@@ -3120,6 +3130,9 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
IdentLocs[i]);
IDecl->setAtEndRange(IdentLocs[i]);
+ if (PrevIDecl)
+ mergeDeclAttributes(IDecl, PrevIDecl);
+
PushOnScopeChains(IDecl, TUScope);
CheckObjCDeclScope(IDecl);
DeclsInGroup.push_back(IDecl);
@@ -3899,6 +3912,55 @@ static void DiagnoseVariableSizedIvars(Sema &S, ObjCContainerDecl *OCD) {
}
}
+static void DiagnoseCategoryDirectMembersProtocolConformance(
+ Sema &S, ObjCProtocolDecl *PDecl, ObjCCategoryDecl *CDecl);
+
+static void DiagnoseCategoryDirectMembersProtocolConformance(
+ Sema &S, ObjCCategoryDecl *CDecl,
+ const llvm::iterator_range<ObjCProtocolList::iterator> &Protocols) {
+ for (auto *PI : Protocols)
+ DiagnoseCategoryDirectMembersProtocolConformance(S, PI, CDecl);
+}
+
+static void DiagnoseCategoryDirectMembersProtocolConformance(
+ Sema &S, ObjCProtocolDecl *PDecl, ObjCCategoryDecl *CDecl) {
+ if (!PDecl->isThisDeclarationADefinition() && PDecl->getDefinition())
+ PDecl = PDecl->getDefinition();
+
+ llvm::SmallVector<const Decl *, 4> DirectMembers;
+ const auto *IDecl = CDecl->getClassInterface();
+ for (auto *MD : PDecl->methods()) {
+ if (!MD->isPropertyAccessor()) {
+ if (const auto *CMD =
+ IDecl->getMethod(MD->getSelector(), MD->isInstanceMethod())) {
+ if (CMD->isDirectMethod())
+ DirectMembers.push_back(CMD);
+ }
+ }
+ }
+ for (auto *PD : PDecl->properties()) {
+ if (const auto *CPD = IDecl->FindPropertyVisibleInPrimaryClass(
+ PD->getIdentifier(),
+ PD->isClassProperty()
+ ? ObjCPropertyQueryKind::OBJC_PR_query_class
+ : ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
+ if (CPD->isDirectProperty())
+ DirectMembers.push_back(CPD);
+ }
+ }
+ if (!DirectMembers.empty()) {
+ S.Diag(CDecl->getLocation(), diag::err_objc_direct_protocol_conformance)
+ << CDecl->IsClassExtension() << CDecl << PDecl << IDecl;
+ for (const auto *MD : DirectMembers)
+ S.Diag(MD->getLocation(), diag::note_direct_member_here);
+ return;
+ }
+
+ // Check on this protocols's referenced protocols, recursively.
+ DiagnoseCategoryDirectMembersProtocolConformance(S, CDecl,
+ PDecl->protocols());
+}
+
// Note: For class/category implementations, allMethods is always null.
Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
ArrayRef<DeclGroupPtrTy> allTUVars) {
@@ -3922,15 +3984,11 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
if (auto *OID = dyn_cast<ObjCImplementationDecl>(CurContext)) {
for (auto PropImpl : OID->property_impls()) {
if (auto *Getter = PropImpl->getGetterMethodDecl())
- if (Getter->isSynthesizedAccessorStub()) {
- OID->makeDeclVisibleInContext(Getter);
+ if (Getter->isSynthesizedAccessorStub())
OID->addDecl(Getter);
- }
if (auto *Setter = PropImpl->getSetterMethodDecl())
- if (Setter->isSynthesizedAccessorStub()) {
- OID->makeDeclVisibleInContext(Setter);
+ if (Setter->isSynthesizedAccessorStub())
OID->addDecl(Setter);
- }
}
}
@@ -4003,6 +4061,8 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
ObjCInterfaceDecl *CCPrimary = C->getClassInterface();
DiagnoseClassExtensionDupMethods(C, CCPrimary);
}
+
+ DiagnoseCategoryDirectMembersProtocolConformance(*this, C, C->protocols());
}
if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(ClassDecl)) {
if (CDecl->getIdentifier())
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index d7695f9d7d7a..851e28741e49 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -99,9 +99,7 @@ ExprResult Sema::ActOnNoexceptSpec(SourceLocation NoexceptLoc,
llvm::APSInt Result;
Converted = VerifyIntegerConstantExpression(
- Converted.get(), &Result,
- diag::err_noexcept_needs_constant_expression,
- /*AllowFold*/ false);
+ Converted.get(), &Result, diag::err_noexcept_needs_constant_expression);
if (!Converted.isInvalid())
EST = !Result ? EST_NoexceptFalse : EST_NoexceptTrue;
return Converted;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index ccae79636f32..45616dadcbee 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -24,10 +24,10 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
+#include "clang/AST/OperationKinds.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Builtins.h"
-#include "clang/Basic/FixedPoint.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
@@ -94,7 +94,7 @@ static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) {
A->getSemanticSpelling() != UnusedAttr::C2x_maybe_unused) {
const Decl *DC = cast_or_null<Decl>(S.getCurObjCLexicalContext());
if (DC && !DC->hasAttr<UnusedAttr>())
- S.Diag(Loc, diag::warn_used_but_marked_unused) << D->getDeclName();
+ S.Diag(Loc, diag::warn_used_but_marked_unused) << D;
}
}
}
@@ -339,11 +339,10 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
// List-items in map clauses on this construct may only refer to the declared
// variable var and entities that could be referenced by a procedure defined
// at the same location
- auto *DMD = dyn_cast<OMPDeclareMapperDecl>(CurContext);
- if (LangOpts.OpenMP && DMD && !CurContext->containsDecl(D) &&
- isa<VarDecl>(D)) {
+ if (LangOpts.OpenMP && isa<VarDecl>(D) &&
+ !isOpenMPDeclareMapperVarDeclAllowed(cast<VarDecl>(D))) {
Diag(Loc, diag::err_omp_declare_mapper_wrong_var)
- << DMD->getVarName().getAsString();
+ << getOpenMPDeclareMapperVarName();
Diag(D->getLocation(), diag::note_entity_declared_at) << D;
return true;
}
@@ -355,6 +354,24 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
diagnoseUseOfInternalDeclInInlineFunction(*this, D, Loc);
+ // CUDA/HIP: Diagnose invalid references of host global variables in device
+ // functions. Reference of device global variables in host functions is
+ // allowed through shadow variables therefore it is not diagnosed.
+ if (LangOpts.CUDAIsDevice) {
+ auto *FD = dyn_cast_or_null<FunctionDecl>(CurContext);
+ auto Target = IdentifyCUDATarget(FD);
+ if (FD && Target != CFT_Host) {
+ const auto *VD = dyn_cast<VarDecl>(D);
+ if (VD && VD->hasGlobalStorage() && !VD->hasAttr<CUDADeviceAttr>() &&
+ !VD->hasAttr<CUDAConstantAttr>() && !VD->hasAttr<CUDASharedAttr>() &&
+ !VD->getType()->isCUDADeviceBuiltinSurfaceType() &&
+ !VD->getType()->isCUDADeviceBuiltinTextureType() &&
+ !VD->isConstexpr() && !VD->getType().isConstQualified())
+ targetDiag(*Locs.begin(), diag::err_ref_bad_target)
+ << /*host*/ 2 << /*variable*/ 1 << VD << Target;
+ }
+ }
+
if (LangOpts.SYCLIsDevice || (LangOpts.OpenMP && LangOpts.OpenMPIsDevice)) {
if (const auto *VD = dyn_cast<ValueDecl>(D))
checkDeviceDecl(VD, Loc);
@@ -697,7 +714,8 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
// C++ [conv.lval]p3:
// If T is cv std::nullptr_t, the result is a null pointer constant.
CastKind CK = T->isNullPtrType() ? CK_NullToPointer : CK_LValueToRValue;
- Res = ImplicitCastExpr::Create(Context, T, CK, E, nullptr, VK_RValue);
+ Res = ImplicitCastExpr::Create(Context, T, CK, E, nullptr, VK_RValue,
+ CurFPFeatureOverrides());
// C11 6.3.2.1p2:
// ... if the lvalue has atomic type, the value has the non-atomic version
@@ -705,7 +723,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
if (const AtomicType *Atomic = T->getAs<AtomicType>()) {
T = Atomic->getValueType().getUnqualifiedType();
Res = ImplicitCastExpr::Create(Context, T, CK_AtomicToNonAtomic, Res.get(),
- nullptr, VK_RValue);
+ nullptr, VK_RValue, FPOptionsOverride());
}
return Res;
@@ -1126,6 +1144,17 @@ static QualType handleFloatConversion(Sema &S, ExprResult &LHS,
bool LHSFloat = LHSType->isRealFloatingType();
bool RHSFloat = RHSType->isRealFloatingType();
+ // N1169 4.1.4: If one of the operands has a floating type and the other
+ // operand has a fixed-point type, the fixed-point operand
+ // is converted to the floating type [...]
+ if (LHSType->isFixedPointType() || RHSType->isFixedPointType()) {
+ if (LHSFloat)
+ RHS = S.ImpCastExprToType(RHS.get(), LHSType, CK_FixedPointToFloating);
+ else if (!IsCompAssign)
+ LHS = S.ImpCastExprToType(LHS.get(), RHSType, CK_FixedPointToFloating);
+ return LHSFloat ? LHSType : RHSType;
+ }
+
// If we have two real floating types, convert the smaller operand
// to the bigger result.
if (LHSFloat && RHSFloat) {
@@ -1152,8 +1181,8 @@ static QualType handleFloatConversion(Sema &S, ExprResult &LHS,
}
assert(RHSFloat);
return handleIntToFloatConversion(S, RHS, LHS, RHSType, LHSType,
- /*convertInt=*/ true,
- /*convertFloat=*/!IsCompAssign);
+ /*ConvertFloat=*/ true,
+ /*ConvertInt=*/!IsCompAssign);
}
/// Diagnose attempts to convert between __float128 and long double if
@@ -1747,7 +1776,7 @@ static ExprResult BuildCookedLiteralOperatorCall(Sema &S, Scope *Scope,
LookupResult R(S, OpName, UDSuffixLoc, Sema::LookupOrdinaryName);
if (S.LookupLiteralOperator(Scope, R, llvm::makeArrayRef(ArgTy, Args.size()),
/*AllowRaw*/ false, /*AllowTemplate*/ false,
- /*AllowStringTemplate*/ false,
+ /*AllowStringTemplatePack*/ false,
/*DiagnoseMissing*/ true) == Sema::LOLR_Error)
return ExprError();
@@ -1852,9 +1881,9 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName);
switch (LookupLiteralOperator(UDLScope, R, ArgTy,
- /*AllowRaw*/ false, /*AllowTemplate*/ false,
- /*AllowStringTemplate*/ true,
- /*DiagnoseMissing*/ true)) {
+ /*AllowRaw*/ false, /*AllowTemplate*/ true,
+ /*AllowStringTemplatePack*/ true,
+ /*DiagnoseMissing*/ true, Lit)) {
case LOLR_Cooked: {
llvm::APInt Len(Context.getIntWidth(SizeType), Literal.GetNumStringChars());
@@ -1865,7 +1894,16 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
return BuildLiteralOperatorCall(R, OpNameInfo, Args, StringTokLocs.back());
}
- case LOLR_StringTemplate: {
+ case LOLR_Template: {
+ TemplateArgumentListInfo ExplicitArgs;
+ TemplateArgument Arg(Lit);
+ TemplateArgumentLocInfo ArgInfo(Lit);
+ ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo));
+ return BuildLiteralOperatorCall(R, OpNameInfo, None, StringTokLocs.back(),
+ &ExplicitArgs);
+ }
+
+ case LOLR_StringTemplatePack: {
TemplateArgumentListInfo ExplicitArgs;
unsigned CharBits = Context.getIntWidth(CharTy);
@@ -1886,7 +1924,6 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
&ExplicitArgs);
}
case LOLR_Raw:
- case LOLR_Template:
case LOLR_ErrorNoDiagnostic:
llvm_unreachable("unexpected literal operator lookup result");
case LOLR_Error:
@@ -1915,6 +1952,35 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
TemplateArgs);
}
+// CUDA/HIP: Check whether a captured reference variable is referencing a
+// host variable in a device or host device lambda.
+static bool isCapturingReferenceToHostVarInCUDADeviceLambda(const Sema &S,
+ VarDecl *VD) {
+ if (!S.getLangOpts().CUDA || !VD->hasInit())
+ return false;
+ assert(VD->getType()->isReferenceType());
+
+ // Check whether the reference variable is referencing a host variable.
+ auto *DRE = dyn_cast<DeclRefExpr>(VD->getInit());
+ if (!DRE)
+ return false;
+ auto *Referee = dyn_cast<VarDecl>(DRE->getDecl());
+ if (!Referee || !Referee->hasGlobalStorage() ||
+ Referee->hasAttr<CUDADeviceAttr>())
+ return false;
+
+ // Check whether the current function is a device or host device lambda.
+ // Check whether the reference variable is a capture by getDeclContext()
+ // since refersToEnclosingVariableOrCapture() is not ready at this point.
+ auto *MD = dyn_cast_or_null<CXXMethodDecl>(S.CurContext);
+ if (MD && MD->getParent()->isLambda() &&
+ MD->getOverloadedOperator() == OO_Call && MD->hasAttr<CUDADeviceAttr>() &&
+ VD->getDeclContext() != MD)
+ return true;
+
+ return false;
+}
+
NonOdrUseReason Sema::getNonOdrUseReasonInCurrentContext(ValueDecl *D) {
// A declaration named in an unevaluated operand never constitutes an odr-use.
if (isUnevaluatedContext())
@@ -1924,9 +1990,16 @@ NonOdrUseReason Sema::getNonOdrUseReasonInCurrentContext(ValueDecl *D) {
// A variable x whose name appears as a potentially-evaluated expression e
// is odr-used by e unless [...] x is a reference that is usable in
// constant expressions.
+ // CUDA/HIP:
+ // If a reference variable referencing a host variable is captured in a
+ // device or host device lambda, the value of the referee must be copied
+ // to the capture and the reference variable must be treated as odr-use
+ // since the value of the referee is not known at compile time and must
+ // be loaded from the captured.
if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (VD->getType()->isReferenceType() &&
!(getLangOpts().OpenMP && isOpenMPCapturedDecl(D)) &&
+ !isCapturingReferenceToHostVarInCUDADeviceLambda(*this, VD) &&
VD->isUsableInConstantExpressions(Context))
return NOUR_Constant;
}
@@ -2061,6 +2134,73 @@ static void emitEmptyLookupTypoDiagnostic(
SemaRef.PDiag(NoteID));
}
+/// Diagnose a lookup that found results in an enclosing class during error
+/// recovery. This usually indicates that the results were found in a dependent
+/// base class that could not be searched as part of a template definition.
+/// Always issues a diagnostic (though this may be only a warning in MS
+/// compatibility mode).
+///
+/// Return \c true if the error is unrecoverable, or \c false if the caller
+/// should attempt to recover using these lookup results.
+bool Sema::DiagnoseDependentMemberLookup(LookupResult &R) {
+ // During a default argument instantiation the CurContext points
+ // to a CXXMethodDecl; but we can't apply a this-> fixit inside a
+ // function parameter list, hence add an explicit check.
+ bool isDefaultArgument =
+ !CodeSynthesisContexts.empty() &&
+ CodeSynthesisContexts.back().Kind ==
+ CodeSynthesisContext::DefaultFunctionArgumentInstantiation;
+ CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext);
+ bool isInstance = CurMethod && CurMethod->isInstance() &&
+ R.getNamingClass() == CurMethod->getParent() &&
+ !isDefaultArgument;
+
+ // There are two ways we can find a class-scope declaration during template
+ // instantiation that we did not find in the template definition: if it is a
+ // member of a dependent base class, or if it is declared after the point of
+ // use in the same class. Distinguish these by comparing the class in which
+ // the member was found to the naming class of the lookup.
+ unsigned DiagID = diag::err_found_in_dependent_base;
+ unsigned NoteID = diag::note_member_declared_at;
+ if (R.getRepresentativeDecl()->getDeclContext()->Equals(R.getNamingClass())) {
+ DiagID = getLangOpts().MSVCCompat ? diag::ext_found_later_in_class
+ : diag::err_found_later_in_class;
+ } else if (getLangOpts().MSVCCompat) {
+ DiagID = diag::ext_found_in_dependent_base;
+ NoteID = diag::note_dependent_member_use;
+ }
+
+ if (isInstance) {
+ // Give a code modification hint to insert 'this->'.
+ Diag(R.getNameLoc(), DiagID)
+ << R.getLookupName()
+ << FixItHint::CreateInsertion(R.getNameLoc(), "this->");
+ CheckCXXThisCapture(R.getNameLoc());
+ } else {
+ // FIXME: Add a FixItHint to insert 'Base::' or 'Derived::' (assuming
+ // they're not shadowed).
+ Diag(R.getNameLoc(), DiagID) << R.getLookupName();
+ }
+
+ for (NamedDecl *D : R)
+ Diag(D->getLocation(), NoteID);
+
+ // Return true if we are inside a default argument instantiation
+ // and the found name refers to an instance member function, otherwise
+ // the caller will try to create an implicit member call and this is wrong
+ // for default arguments.
+ //
+ // FIXME: Is this special case necessary? We could allow the caller to
+ // diagnose this.
+ if (isDefaultArgument && ((*R.begin())->isCXXInstanceMember())) {
+ Diag(R.getNameLoc(), diag::err_member_call_without_object);
+ return true;
+ }
+
+ // Tell the callee to try to recover.
+ return false;
+}
+
/// Diagnose an empty lookup.
///
/// \return false if new lookup candidates were found
@@ -2092,46 +2232,20 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
// Don't give errors about ambiguities in this lookup.
R.suppressDiagnostics();
- // During a default argument instantiation the CurContext points
- // to a CXXMethodDecl; but we can't apply a this-> fixit inside a
- // function parameter list, hence add an explicit check.
- bool isDefaultArgument =
- !CodeSynthesisContexts.empty() &&
- CodeSynthesisContexts.back().Kind ==
- CodeSynthesisContext::DefaultFunctionArgumentInstantiation;
- CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext);
- bool isInstance = CurMethod &&
- CurMethod->isInstance() &&
- DC == CurMethod->getParent() && !isDefaultArgument;
-
- // Give a code modification hint to insert 'this->'.
- // TODO: fixit for inserting 'Base<T>::' in the other cases.
- // Actually quite difficult!
- if (getLangOpts().MSVCCompat)
- diagnostic = diag::ext_found_via_dependent_bases_lookup;
- if (isInstance) {
- Diag(R.getNameLoc(), diagnostic) << Name
- << FixItHint::CreateInsertion(R.getNameLoc(), "this->");
- CheckCXXThisCapture(R.getNameLoc());
- } else {
- Diag(R.getNameLoc(), diagnostic) << Name;
- }
-
- // Do we really want to note all of these?
- for (NamedDecl *D : R)
- Diag(D->getLocation(), diag::note_dependent_var_use);
-
- // Return true if we are inside a default argument instantiation
- // and the found name refers to an instance member function, otherwise
- // the function calling DiagnoseEmptyLookup will try to create an
- // implicit member call and this is wrong for default argument.
- if (isDefaultArgument && ((*R.begin())->isCXXInstanceMember())) {
- Diag(R.getNameLoc(), diag::err_member_call_without_object);
- return true;
+ // If there's a best viable function among the results, only mention
+ // that one in the notes.
+ OverloadCandidateSet Candidates(R.getNameLoc(),
+ OverloadCandidateSet::CSK_Normal);
+ AddOverloadedCallCandidates(R, ExplicitTemplateArgs, Args, Candidates);
+ OverloadCandidateSet::iterator Best;
+ if (Candidates.BestViableFunction(*this, R.getNameLoc(), Best) ==
+ OR_Success) {
+ R.clear();
+ R.addDecl(Best->FoundDecl.getDecl(), Best->FoundDecl.getAccess());
+ R.resolveKind();
}
- // Tell the callee to try to recover.
- return false;
+ return DiagnoseDependentMemberLookup(R);
}
R.clear();
@@ -2577,6 +2691,13 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr(
NameInfo, /*TemplateArgs=*/nullptr);
if (R.empty()) {
+ // Don't diagnose problems with invalid record decl, the secondary no_member
+ // diagnostic during template instantiation is likely bogus, e.g. if a class
+ // is invalid because it's derived from an invalid base class, then missing
+ // members were likely supposed to be inherited.
+ if (const auto *CD = dyn_cast<CXXRecordDecl>(DC))
+ if (CD->isInvalidDecl())
+ return ExprError();
Diag(NameInfo.getLoc(), diag::err_no_member)
<< NameInfo.getName() << DC << SS.getRange();
return ExprError();
@@ -2730,8 +2851,7 @@ ExprResult Sema::BuildIvarRefExpr(Scope *S, SourceLocation Loc,
// turn this into Self->ivar, just return a BareIVarExpr or something.
IdentifierInfo &II = Context.Idents.get("self");
UnqualifiedId SelfName;
- SelfName.setIdentifier(&II, SourceLocation());
- SelfName.setKind(UnqualifiedIdKind::IK_ImplicitSelfParam);
+ SelfName.setImplicitSelfParam(&II);
CXXScopeSpec SelfScopeSpec;
SourceLocation TemplateKWLoc;
ExprResult SelfExpr =
@@ -2792,21 +2912,24 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
/// Cast a base object to a member's actual type.
///
-/// Logically this happens in three phases:
+/// There are two relevant checks:
+///
+/// C++ [class.access.base]p7:
///
-/// * First we cast from the base type to the naming class.
-/// The naming class is the class into which we were looking
-/// when we found the member; it's the qualifier type if a
-/// qualifier was provided, and otherwise it's the base type.
+/// If a class member access operator [...] is used to access a non-static
+/// data member or non-static member function, the reference is ill-formed if
+/// the left operand [...] cannot be implicitly converted to a pointer to the
+/// naming class of the right operand.
///
-/// * Next we cast from the naming class to the declaring class.
-/// If the member we found was brought into a class's scope by
-/// a using declaration, this is that class; otherwise it's
-/// the class declaring the member.
+/// C++ [expr.ref]p7:
///
-/// * Finally we cast from the declaring class to the "true"
-/// declaring class of the member. This conversion does not
-/// obey access control.
+/// If E2 is a non-static data member or a non-static member function, the
+/// program is ill-formed if the class of which E2 is directly a member is an
+/// ambiguous base (11.8) of the naming class (11.9.3) of E2.
+///
+/// Note that the latter check does not consider access; the access of the
+/// "real" base class is checked as appropriate when checking the access of the
+/// member name.
ExprResult
Sema::PerformObjectMemberConversion(Expr *From,
NestedNameSpecifier *Qualifier,
@@ -2930,45 +3053,10 @@ Sema::PerformObjectMemberConversion(Expr *From,
}
}
- bool IgnoreAccess = false;
-
- // If we actually found the member through a using declaration, cast
- // down to the using declaration's type.
- //
- // Pointer equality is fine here because only one declaration of a
- // class ever has member declarations.
- if (FoundDecl->getDeclContext() != Member->getDeclContext()) {
- assert(isa<UsingShadowDecl>(FoundDecl));
- QualType URecordType = Context.getTypeDeclType(
- cast<CXXRecordDecl>(FoundDecl->getDeclContext()));
-
- // We only need to do this if the naming-class to declaring-class
- // conversion is non-trivial.
- if (!Context.hasSameUnqualifiedType(FromRecordType, URecordType)) {
- assert(IsDerivedFrom(FromLoc, FromRecordType, URecordType));
- CXXCastPath BasePath;
- if (CheckDerivedToBaseConversion(FromRecordType, URecordType,
- FromLoc, FromRange, &BasePath))
- return ExprError();
-
- QualType UType = URecordType;
- if (PointerConversions)
- UType = Context.getPointerType(UType);
- From = ImpCastExprToType(From, UType, CK_UncheckedDerivedToBase,
- VK, &BasePath).get();
- FromType = UType;
- FromRecordType = URecordType;
- }
-
- // We don't do access control for the conversion from the
- // declaring class to the true declaring class.
- IgnoreAccess = true;
- }
-
CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(FromRecordType, DestRecordType,
FromLoc, FromRange, &BasePath,
- IgnoreAccess))
+ /*IgnoreAccess=*/true))
return ExprError();
return ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase,
@@ -3208,6 +3296,17 @@ ExprResult Sema::BuildDeclarationNameExpr(
break;
}
+ // [expr.prim.id.unqual]p2:
+ // If the entity is a template parameter object for a template
+ // parameter of type T, the type of the expression is const T.
+ // [...] The expression is an lvalue if the entity is a [...] template
+ // parameter object.
+ if (type->isRecordType()) {
+ type = type.getUnqualifiedType().withConst();
+ valueKind = VK_LValue;
+ break;
+ }
+
// For non-references, we need to strip qualifiers just in case
// the template parameter was declared as 'const int' or whatever.
valueKind = VK_RValue;
@@ -3307,8 +3406,9 @@ ExprResult Sema::BuildDeclarationNameExpr(
case Decl::MSProperty:
case Decl::MSGuid:
- // FIXME: Should MSGuidDecl be subject to capture in OpenMP,
- // or duplicated between host and device?
+ case Decl::TemplateParamObject:
+ // FIXME: Should MSGuidDecl and template parameter objects be subject to
+ // capture in OpenMP, or duplicated between host and device?
valueKind = VK_LValue;
break;
@@ -3409,70 +3509,6 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
return PredefinedExpr::Create(Context, Loc, ResTy, IK, SL);
}
-static std::pair<QualType, StringLiteral *>
-GetUniqueStableNameInfo(ASTContext &Context, QualType OpType,
- SourceLocation OpLoc, PredefinedExpr::IdentKind K) {
- std::pair<QualType, StringLiteral*> Result{{}, nullptr};
-
- if (OpType->isDependentType()) {
- Result.first = Context.DependentTy;
- return Result;
- }
-
- std::string Str = PredefinedExpr::ComputeName(Context, K, OpType);
- llvm::APInt Length(32, Str.length() + 1);
- Result.first =
- Context.adjustStringLiteralBaseType(Context.CharTy.withConst());
- Result.first = Context.getConstantArrayType(
- Result.first, Length, nullptr, ArrayType::Normal, /*IndexTypeQuals*/ 0);
- Result.second = StringLiteral::Create(Context, Str, StringLiteral::Ascii,
- /*Pascal*/ false, Result.first, OpLoc);
- return Result;
-}
-
-ExprResult Sema::BuildUniqueStableName(SourceLocation OpLoc,
- TypeSourceInfo *Operand) {
- QualType ResultTy;
- StringLiteral *SL;
- std::tie(ResultTy, SL) = GetUniqueStableNameInfo(
- Context, Operand->getType(), OpLoc, PredefinedExpr::UniqueStableNameType);
-
- return PredefinedExpr::Create(Context, OpLoc, ResultTy,
- PredefinedExpr::UniqueStableNameType, SL,
- Operand);
-}
-
-ExprResult Sema::BuildUniqueStableName(SourceLocation OpLoc,
- Expr *E) {
- QualType ResultTy;
- StringLiteral *SL;
- std::tie(ResultTy, SL) = GetUniqueStableNameInfo(
- Context, E->getType(), OpLoc, PredefinedExpr::UniqueStableNameExpr);
-
- return PredefinedExpr::Create(Context, OpLoc, ResultTy,
- PredefinedExpr::UniqueStableNameExpr, SL, E);
-}
-
-ExprResult Sema::ActOnUniqueStableNameExpr(SourceLocation OpLoc,
- SourceLocation L, SourceLocation R,
- ParsedType Ty) {
- TypeSourceInfo *TInfo = nullptr;
- QualType T = GetTypeFromParser(Ty, &TInfo);
-
- if (T.isNull())
- return ExprError();
- if (!TInfo)
- TInfo = Context.getTrivialTypeSourceInfo(T, OpLoc);
-
- return BuildUniqueStableName(OpLoc, TInfo);
-}
-
-ExprResult Sema::ActOnUniqueStableNameExpr(SourceLocation OpLoc,
- SourceLocation L, SourceLocation R,
- Expr *E) {
- return BuildUniqueStableName(OpLoc, E);
-}
-
ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
PredefinedExpr::IdentKind IK;
@@ -3675,7 +3711,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName);
switch (LookupLiteralOperator(UDLScope, R, CookedTy,
/*AllowRaw*/ true, /*AllowTemplate*/ true,
- /*AllowStringTemplate*/ false,
+ /*AllowStringTemplatePack*/ false,
/*DiagnoseMissing*/ !Literal.isImaginary)) {
case LOLR_ErrorNoDiagnostic:
// Lookup failure for imaginary constants isn't fatal, there's still the
@@ -3730,7 +3766,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
return BuildLiteralOperatorCall(R, OpNameInfo, None, TokLoc,
&ExplicitArgs);
}
- case LOLR_StringTemplate:
+ case LOLR_StringTemplatePack:
llvm_unreachable("unexpected literal operator lookup result");
}
}
@@ -3804,8 +3840,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
if (Ty == Context.DoubleTy) {
if (getLangOpts().SinglePrecisionConstants) {
- const BuiltinType *BTy = Ty->getAs<BuiltinType>();
- if (BTy->getKind() != BuiltinType::Float) {
+ if (Ty->castAs<BuiltinType>()->getKind() != BuiltinType::Float) {
Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
}
} else if (getLangOpts().OpenCL &&
@@ -4053,7 +4088,7 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
bool IsUnevaluatedOperand =
(ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf ||
- ExprKind == UETT_PreferredAlignOf);
+ ExprKind == UETT_PreferredAlignOf || ExprKind == UETT_VecStep);
if (IsUnevaluatedOperand) {
ExprResult Result = CheckUnevaluatedOperand(E);
if (Result.isInvalid())
@@ -4061,6 +4096,16 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
E = Result.get();
}
+ // The operand for sizeof and alignof is in an unevaluated expression context,
+ // so side effects could result in unintended consequences.
+ // Exclude instantiation-dependent expressions, because 'sizeof' is sometimes
+ // used to build SFINAE gadgets.
+ // FIXME: Should we consider instantiation-dependent operands to 'alignof'?
+ if (IsUnevaluatedOperand && !inTemplateInstantiation() &&
+ !E->isInstantiationDependent() &&
+ E->HasSideEffects(Context, false))
+ Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
+
if (ExprKind == UETT_VecStep)
return CheckVecStepTraitOperandType(*this, ExprTy, E->getExprLoc(),
E->getSourceRange());
@@ -4097,12 +4142,6 @@ 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 (IsUnevaluatedOperand && !inTemplateInstantiation() &&
- E->HasSideEffects(Context, false))
- Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
-
if (CheckObjCTraitOperandConstraints(*this, ExprTy, E->getExprLoc(),
E->getSourceRange(), ExprKind))
return true;
@@ -4345,7 +4384,6 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T,
case Type::UnaryTransform:
case Type::Attributed:
case Type::SubstTemplateTypeParm:
- case Type::PackExpansion:
case Type::MacroQualified:
// Keep walking after single level desugaring.
T = T.getSingleStepDesugaredType(Context);
@@ -4593,8 +4631,8 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
<< SourceRange(base->getBeginLoc(), rbLoc);
return ExprError();
}
- // If the base is either a MatrixSubscriptExpr or a matrix type, try to create
- // a new MatrixSubscriptExpr.
+ // If the base is a MatrixSubscriptExpr, try to create a new
+ // MatrixSubscriptExpr.
auto *matSubscriptE = dyn_cast<MatrixSubscriptExpr>(base);
if (matSubscriptE) {
if (CheckAndReportCommaError(idx))
@@ -4605,34 +4643,13 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
return CreateBuiltinMatrixSubscriptExpr(
matSubscriptE->getBase(), matSubscriptE->getRowIdx(), idx, rbLoc);
}
- Expr *matrixBase = base;
- bool IsMSPropertySubscript = isMSPropertySubscriptExpr(*this, base);
- if (!IsMSPropertySubscript) {
- ExprResult result = CheckPlaceholderExpr(base);
- if (!result.isInvalid())
- matrixBase = result.get();
- }
- if (matrixBase->getType()->isMatrixType()) {
- if (CheckAndReportCommaError(idx))
- return ExprError();
-
- return CreateBuiltinMatrixSubscriptExpr(matrixBase, idx, nullptr, rbLoc);
- }
-
- // A comma-expression as the index is deprecated in C++2a onwards.
- if (getLangOpts().CPlusPlus20 &&
- ((isa<BinaryOperator>(idx) && cast<BinaryOperator>(idx)->isCommaOp()) ||
- (isa<CXXOperatorCallExpr>(idx) &&
- cast<CXXOperatorCallExpr>(idx)->getOperator() == OO_Comma))) {
- Diag(idx->getExprLoc(), diag::warn_deprecated_comma_subscript)
- << SourceRange(base->getBeginLoc(), rbLoc);
- }
// Handle any non-overload placeholder types in the base and index
// expressions. We can't handle overloads here because the other
// operand might be an overloadable type, in which case the overload
// resolution for the operator overload should get the first crack
// at the overload.
+ bool IsMSPropertySubscript = false;
if (base->getType()->isNonOverloadPlaceholderType()) {
IsMSPropertySubscript = isMSPropertySubscriptExpr(*this, base);
if (!IsMSPropertySubscript) {
@@ -4642,6 +4659,24 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
base = result.get();
}
}
+
+ // If the base is a matrix type, try to create a new MatrixSubscriptExpr.
+ if (base->getType()->isMatrixType()) {
+ if (CheckAndReportCommaError(idx))
+ return ExprError();
+
+ return CreateBuiltinMatrixSubscriptExpr(base, idx, nullptr, rbLoc);
+ }
+
+ // A comma-expression as the index is deprecated in C++2a onwards.
+ if (getLangOpts().CPlusPlus20 &&
+ ((isa<BinaryOperator>(idx) && cast<BinaryOperator>(idx)->isCommaOp()) ||
+ (isa<CXXOperatorCallExpr>(idx) &&
+ cast<CXXOperatorCallExpr>(idx)->getOperator() == OO_Comma))) {
+ Diag(idx->getExprLoc(), diag::warn_deprecated_comma_subscript)
+ << SourceRange(base->getBeginLoc(), rbLoc);
+ }
+
if (idx->getType()->isNonOverloadPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(idx);
if (result.isInvalid()) return ExprError();
@@ -4741,12 +4776,13 @@ ExprResult Sema::CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx,
return nullptr;
}
- llvm::APSInt Idx;
- if (IndexExpr->isIntegerConstantExpr(Idx, Context) &&
- (Idx < 0 || Idx >= Dim)) {
- Diag(IndexExpr->getBeginLoc(), diag::err_matrix_index_outside_range)
- << IsColumnIdx << Dim;
- return nullptr;
+ if (Optional<llvm::APSInt> Idx =
+ IndexExpr->getIntegerConstantExpr(Context)) {
+ if ((*Idx < 0 || *Idx >= Dim)) {
+ Diag(IndexExpr->getBeginLoc(), diag::err_matrix_index_outside_range)
+ << IsColumnIdx << Dim;
+ return nullptr;
+ }
}
ExprResult ConvExpr =
@@ -4780,6 +4816,9 @@ void Sema::CheckAddressOfNoDeref(const Expr *E) {
}
void Sema::CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E) {
+ if (isUnevaluatedContext())
+ return;
+
QualType ResultTy = E->getType();
ExpressionEvaluationContextRecord &LastRecord = ExprEvalContexts.back();
@@ -5162,12 +5201,11 @@ ExprResult Sema::ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc,
IsCorrect = false;
continue;
}
- llvm::APSInt Result;
- bool IsConstant = Step->isIntegerConstantExpr(Result, Context);
+ Optional<llvm::APSInt> Result = Step->getIntegerConstantExpr(Context);
// OpenMP 5.0, 2.1.6 Iterators, Restrictions
// If the step expression of a range-specification equals zero, the
// behavior is unspecified.
- if (IsConstant && Result.isNullValue()) {
+ if (Result && Result->isNullValue()) {
Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
<< Step << Step->getSourceRange();
IsCorrect = false;
@@ -5567,9 +5605,8 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
return true;
}
- Diag(CallLoc,
- diag::err_use_of_default_argument_to_function_declared_later) <<
- FD << cast<CXXRecordDecl>(FD->getDeclContext())->getDeclName();
+ Diag(CallLoc, diag::err_use_of_default_argument_to_function_declared_later)
+ << FD << cast<CXXRecordDecl>(FD->getDeclContext());
Diag(UnparsedDefaultArgLocs[Param],
diag::note_default_argument_declared_here);
return true;
@@ -6021,6 +6058,9 @@ static bool isPlaceholderToRemoveAsArg(QualType type) {
#define SVE_TYPE(Name, Id, SingletonId) \
case BuiltinType::Id:
#include "clang/Basic/AArch64SVEACLETypes.def"
+#define PPC_VECTOR_TYPE(Name, Id, Size) \
+ case BuiltinType::Id:
+#include "clang/Basic/PPCTypes.def"
#define PLACEHOLDER_TYPE(ID, SINGLETON_ID)
#define BUILTIN_TYPE(ID, SINGLETON_ID) case BuiltinType::ID:
#include "clang/AST/BuiltinTypes.def"
@@ -6069,8 +6109,6 @@ 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;
@@ -6158,6 +6196,7 @@ static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context,
Params.push_back(Parm);
}
OverloadDecl->setParams(Params);
+ Sema->mergeDeclAttributes(OverloadDecl, FDecl);
return OverloadDecl;
}
@@ -6273,7 +6312,8 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
MultiExprArg ArgExprs, SourceLocation RParenLoc,
Expr *ExecConfig) {
ExprResult Call =
- BuildCallExpr(Scope, Fn, LParenLoc, ArgExprs, RParenLoc, ExecConfig);
+ BuildCallExpr(Scope, Fn, LParenLoc, ArgExprs, RParenLoc, ExecConfig,
+ /*IsExecConfig=*/false, /*AllowRecovery=*/true);
if (Call.isInvalid())
return Call;
@@ -6301,7 +6341,8 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
/// locations.
ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
MultiExprArg ArgExprs, SourceLocation RParenLoc,
- Expr *ExecConfig, bool IsExecConfig) {
+ Expr *ExecConfig, bool IsExecConfig,
+ bool AllowRecovery) {
// Since this might be a postfix expression, get rid of ParenListExprs.
ExprResult Result = MaybeConvertParenListExprToParenExpr(Scope, Fn);
if (Result.isInvalid()) return ExprError();
@@ -6322,7 +6363,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
}
return CallExpr::Create(Context, Fn, /*Args=*/{}, Context.VoidTy,
- VK_RValue, RParenLoc);
+ VK_RValue, RParenLoc, CurFPFeatureOverrides());
}
if (Fn->getType() == Context.PseudoObjectTy) {
ExprResult result = CheckPlaceholderExpr(Fn);
@@ -6336,7 +6377,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
if (ExecConfig) {
return CUDAKernelCallExpr::Create(
Context, Fn, cast<CallExpr>(ExecConfig), ArgExprs,
- Context.DependentTy, VK_RValue, RParenLoc);
+ Context.DependentTy, VK_RValue, RParenLoc, CurFPFeatureOverrides());
} else {
tryImplicitlyCaptureThisIfImplicitMemberFunctionAccessWithDependentArgs(
@@ -6344,7 +6385,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
Fn->getBeginLoc());
return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy,
- VK_RValue, RParenLoc);
+ VK_RValue, RParenLoc, CurFPFeatureOverrides());
}
}
@@ -6361,7 +6402,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
if (Fn->getType() == Context.BoundMemberTy) {
return BuildCallToMemberFunction(Scope, Fn, LParenLoc, ArgExprs,
- RParenLoc);
+ RParenLoc, AllowRecovery);
}
}
@@ -6373,14 +6414,14 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
if (!find.HasFormOfMemberPointer) {
if (Expr::hasAnyTypeDependentArguments(ArgExprs))
return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy,
- VK_RValue, RParenLoc);
+ VK_RValue, RParenLoc, CurFPFeatureOverrides());
OverloadExpr *ovl = find.Expression;
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(ovl))
return BuildOverloadedCallExpr(
Scope, Fn, ULE, LParenLoc, ArgExprs, RParenLoc, ExecConfig,
/*AllowTypoCorrection=*/true, find.IsAddressOfOperand);
return BuildCallToMemberFunction(Scope, Fn, LParenLoc, ArgExprs,
- RParenLoc);
+ RParenLoc, AllowRecovery);
}
}
@@ -6433,6 +6474,21 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
checkDirectCallValidity(*this, Fn, FD, ArgExprs);
}
+ if (Context.isDependenceAllowed() &&
+ (Fn->isTypeDependent() || Expr::hasAnyTypeDependentArguments(ArgExprs))) {
+ assert(!getLangOpts().CPlusPlus);
+ assert((Fn->containsErrors() ||
+ llvm::any_of(ArgExprs,
+ [](clang::Expr *E) { return E->containsErrors(); })) &&
+ "should only occur in error-recovery path.");
+ QualType ReturnType =
+ llvm::isa_and_nonnull<FunctionDecl>(NDecl)
+ ? cast<FunctionDecl>(NDecl)->getCallResultType()
+ : Context.DependentTy;
+ return CallExpr::Create(Context, Fn, ArgExprs, ReturnType,
+ Expr::getValueKindForType(ReturnType), RParenLoc,
+ CurFPFeatureOverrides());
+ }
return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs, RParenLoc,
ExecConfig, IsExecConfig);
}
@@ -6564,15 +6620,16 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (Config) {
assert(UsesADL == ADLCallKind::NotADL &&
"CUDAKernelCallExpr should not use ADL");
- TheCall =
- CUDAKernelCallExpr::Create(Context, Fn, cast<CallExpr>(Config), Args,
- ResultTy, VK_RValue, RParenLoc, NumParams);
+ TheCall = CUDAKernelCallExpr::Create(Context, Fn, cast<CallExpr>(Config),
+ Args, ResultTy, VK_RValue, RParenLoc,
+ CurFPFeatureOverrides(), NumParams);
} else {
- TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue,
- RParenLoc, NumParams, UsesADL);
+ TheCall =
+ CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, RParenLoc,
+ CurFPFeatureOverrides(), NumParams, UsesADL);
}
- if (!getLangOpts().CPlusPlus) {
+ if (!Context.isDependenceAllowed()) {
// Forget about the nulled arguments since typo correction
// do not handle them well.
TheCall->shrinkNumArgs(Args.size());
@@ -6596,10 +6653,11 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (Config)
TheCall = CUDAKernelCallExpr::Create(
Context, Fn, cast<CallExpr>(Config), Args, ResultTy, VK_RValue,
- RParenLoc, NumParams);
+ RParenLoc, CurFPFeatureOverrides(), NumParams);
else
- TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue,
- RParenLoc, NumParams, UsesADL);
+ TheCall =
+ CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, RParenLoc,
+ CurFPFeatureOverrides(), NumParams, UsesADL);
}
// We can now handle the nulled arguments for the default arguments.
TheCall->setNumArgsUnsafe(std::max<unsigned>(Args.size(), NumParams));
@@ -6960,9 +7018,9 @@ void Sema::maybeExtendBlockObject(ExprResult &E) {
// Only do this in an r-value context.
if (!getLangOpts().ObjCAutoRefCount) return;
- E = ImplicitCastExpr::Create(Context, E.get()->getType(),
- CK_ARCExtendBlockObject, E.get(),
- /*base path*/ nullptr, VK_RValue);
+ E = ImplicitCastExpr::Create(
+ Context, E.get()->getType(), CK_ARCExtendBlockObject, E.get(),
+ /*base path*/ nullptr, VK_RValue, FPOptionsOverride());
Cleanup.setExprNeedsCleanups(true);
}
@@ -7041,6 +7099,7 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
case Type::STK_Integral:
return CK_FixedPointToIntegral;
case Type::STK_Floating:
+ return CK_FixedPointToFloating;
case Type::STK_IntegralComplex:
case Type::STK_FloatingComplex:
Diag(Src.get()->getExprLoc(),
@@ -7113,10 +7172,7 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
case Type::STK_MemberPointer:
llvm_unreachable("member pointer type in C");
case Type::STK_FixedPoint:
- Diag(Src.get()->getExprLoc(),
- diag::err_unimplemented_conversion_with_fixed_point_type)
- << SrcTy;
- return CK_IntegralCast;
+ return CK_FloatingToFixedPoint;
}
llvm_unreachable("Should have returned before this");
@@ -7211,6 +7267,28 @@ static bool breakDownVectorType(QualType type, uint64_t &len,
return true;
}
+/// Are the two types SVE-bitcast-compatible types? I.e. is bitcasting from the
+/// first SVE type (e.g. an SVE VLAT) to the second type (e.g. an SVE VLST)
+/// allowed?
+///
+/// This will also return false if the two given types do not make sense from
+/// the perspective of SVE bitcasts.
+bool Sema::isValidSveBitcast(QualType srcTy, QualType destTy) {
+ assert(srcTy->isVectorType() || destTy->isVectorType());
+
+ auto ValidScalableConversion = [](QualType FirstType, QualType SecondType) {
+ if (!FirstType->isSizelessBuiltinType())
+ return false;
+
+ const auto *VecTy = SecondType->getAs<VectorType>();
+ return VecTy &&
+ VecTy->getVectorKind() == VectorType::SveFixedLengthDataVector;
+ };
+
+ return ValidScalableConversion(srcTy, destTy) ||
+ ValidScalableConversion(destTy, srcTy);
+}
+
/// Are the two types lax-compatible vector types? That is, given
/// that one of them is a vector, do they have equal storage sizes,
/// where the storage size is the number of elements times the element
@@ -7401,7 +7479,7 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
}
if (PE || PLE->getNumExprs() == 1) {
Expr *E = (PE ? PE->getSubExpr() : PLE->getExpr(0));
- if (!E->getType()->isVectorType())
+ if (!E->isTypeDependent() && !E->getType()->isVectorType())
isVectorLiteral = true;
}
else
@@ -8059,6 +8137,16 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
VK = VK_RValue;
OK = OK_Ordinary;
+ if (Context.isDependenceAllowed() &&
+ (Cond.get()->isTypeDependent() || LHS.get()->isTypeDependent() ||
+ RHS.get()->isTypeDependent())) {
+ assert(!getLangOpts().CPlusPlus);
+ assert((Cond.get()->containsErrors() || LHS.get()->containsErrors() ||
+ RHS.get()->containsErrors()) &&
+ "should only occur in error-recovery path.");
+ return Context.DependentTy;
+ }
+
// The OpenCL operator with a vector condition is sufficiently
// different to merit its own checker.
if ((getLangOpts().OpenCL && Cond.get()->getType()->isVectorType()) ||
@@ -8106,6 +8194,15 @@ 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()) {
+ // Disallow invalid arithmetic conversions, such as those between ExtInts of
+ // different sizes, or between ExtInts and other types.
+ if (ResTy.isNull() && (LHSTy->isExtIntType() || RHSTy->isExtIntType())) {
+ Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
+ << LHSTy << RHSTy << LHS.get()->getSourceRange()
+ << RHS.get()->getSourceRange();
+ return QualType();
+ }
+
LHS = ImpCastExprToType(LHS.get(), ResTy, PrepareScalarCast(LHS, ResTy));
RHS = ImpCastExprToType(RHS.get(), ResTy, PrepareScalarCast(RHS, ResTy));
@@ -8363,7 +8460,7 @@ static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode,
Expr **RHSExprs) {
// Don't strip parenthesis: we should not warn if E is in parenthesis.
E = E->IgnoreImpCasts();
- E = E->IgnoreConversionOperator();
+ E = E->IgnoreConversionOperatorSingleStep();
E = E->IgnoreImpCasts();
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) {
E = MTE->getSubExpr();
@@ -8470,8 +8567,12 @@ static QualType computeConditionalNullability(QualType ResTy, bool IsBin,
auto GetNullability = [&Ctx](QualType Ty) {
Optional<NullabilityKind> Kind = Ty->getNullability(Ctx);
- if (Kind)
+ if (Kind) {
+ // For our purposes, treat _Nullable_result as _Nullable.
+ if (*Kind == NullabilityKind::NullableResult)
+ return NullabilityKind::Nullable;
return *Kind;
+ }
return NullabilityKind::Unspecified;
};
@@ -8516,7 +8617,7 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
SourceLocation ColonLoc,
Expr *CondExpr, Expr *LHSExpr,
Expr *RHSExpr) {
- if (!getLangOpts().CPlusPlus) {
+ if (!Context.isDependenceAllowed()) {
// C cannot handle TypoExpr nodes in the condition because it
// doesn't handle dependent types properly, so make sure any TypoExprs have
// been dealt with before checking the operands.
@@ -8997,6 +9098,15 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
}
}
+ // Allow assignments between fixed-length and sizeless SVE vectors.
+ if ((LHSType->isSizelessBuiltinType() && RHSType->isVectorType()) ||
+ (LHSType->isVectorType() && RHSType->isSizelessBuiltinType()))
+ if (Context.areCompatibleSveTypes(LHSType, RHSType) ||
+ Context.areLaxCompatibleSveTypes(LHSType, RHSType)) {
+ Kind = CK_BitCast;
+ return Compatible;
+ }
+
return Incompatible;
}
@@ -9781,6 +9891,10 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
const VectorType *RHSVecType = RHSType->getAs<VectorType>();
assert(LHSVecType || RHSVecType);
+ if ((LHSVecType && LHSVecType->getElementType()->isBFloat16Type()) ||
+ (RHSVecType && RHSVecType->getElementType()->isBFloat16Type()))
+ return InvalidOperands(Loc, LHS, RHS);
+
// AltiVec-style "vector bool op vector bool" combinations are allowed
// for some operators but not others.
if (!AllowBothBool &&
@@ -9827,6 +9941,44 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
}
}
+ // Expressions containing fixed-length and sizeless SVE vectors are invalid
+ // since the ambiguity can affect the ABI.
+ auto IsSveConversion = [](QualType FirstType, QualType SecondType) {
+ const VectorType *VecType = SecondType->getAs<VectorType>();
+ return FirstType->isSizelessBuiltinType() && VecType &&
+ (VecType->getVectorKind() == VectorType::SveFixedLengthDataVector ||
+ VecType->getVectorKind() ==
+ VectorType::SveFixedLengthPredicateVector);
+ };
+
+ if (IsSveConversion(LHSType, RHSType) || IsSveConversion(RHSType, LHSType)) {
+ Diag(Loc, diag::err_typecheck_sve_ambiguous) << LHSType << RHSType;
+ return QualType();
+ }
+
+ // Expressions containing GNU and SVE (fixed or sizeless) vectors are invalid
+ // since the ambiguity can affect the ABI.
+ auto IsSveGnuConversion = [](QualType FirstType, QualType SecondType) {
+ const VectorType *FirstVecType = FirstType->getAs<VectorType>();
+ const VectorType *SecondVecType = SecondType->getAs<VectorType>();
+
+ if (FirstVecType && SecondVecType)
+ return FirstVecType->getVectorKind() == VectorType::GenericVector &&
+ (SecondVecType->getVectorKind() ==
+ VectorType::SveFixedLengthDataVector ||
+ SecondVecType->getVectorKind() ==
+ VectorType::SveFixedLengthPredicateVector);
+
+ return FirstType->isSizelessBuiltinType() && SecondVecType &&
+ SecondVecType->getVectorKind() == VectorType::GenericVector;
+ };
+
+ if (IsSveGnuConversion(LHSType, RHSType) ||
+ IsSveGnuConversion(RHSType, LHSType)) {
+ Diag(Loc, diag::err_typecheck_sve_gnu_ambiguous) << LHSType << RHSType;
+ return QualType();
+ }
+
// If there's a vector type and a scalar, try to convert the scalar to
// the vector element type and splat.
unsigned DiagID = diag::err_typecheck_vector_not_convertable;
@@ -9981,7 +10133,7 @@ static void DiagnoseDivisionSizeofPointerOrArray(Sema &S, Expr *LHS, Expr *RHS,
QualType RHSTy;
if (RUE->isArgumentType())
- RHSTy = RUE->getArgumentType();
+ RHSTy = RUE->getArgumentType().getNonReferenceType();
else
RHSTy = RUE->getArgumentExpr()->IgnoreParens()->getType();
@@ -9999,7 +10151,7 @@ static void DiagnoseDivisionSizeofPointerOrArray(Sema &S, Expr *LHS, Expr *RHS,
QualType ArrayElemTy = ArrayTy->getElementType();
if (ArrayElemTy != S.Context.getBaseElementType(ArrayTy) ||
ArrayElemTy->isDependentType() || RHSTy->isDependentType() ||
- ArrayElemTy->isCharType() ||
+ RHSTy->isReferenceType() || ArrayElemTy->isCharType() ||
S.Context.getTypeSize(ArrayElemTy) == S.Context.getTypeSize(RHSTy))
return;
S.Diag(Loc, diag::warn_division_sizeof_array)
@@ -10589,9 +10741,13 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
}
QualType LHSExprType = LHS.get()->getType();
- uint64_t LeftSize = LHSExprType->isExtIntType()
- ? S.Context.getIntWidth(LHSExprType)
- : S.Context.getTypeSize(LHSExprType);
+ uint64_t LeftSize = S.Context.getTypeSize(LHSExprType);
+ if (LHSExprType->isExtIntType())
+ LeftSize = S.Context.getIntWidth(LHSExprType);
+ else if (LHSExprType->isFixedPointType()) {
+ auto FXSema = S.Context.getFixedPointSemantics(LHSExprType);
+ LeftSize = FXSema.getWidth() - (unsigned)FXSema.hasUnsignedPadding();
+ }
llvm::APInt LeftBits(Right.getBitWidth(), LeftSize);
if (Right.uge(LeftBits)) {
S.DiagRuntimeBehavior(Loc, RHS.get(),
@@ -10600,7 +10756,8 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
return;
}
- if (Opc != BO_Shl)
+ // FIXME: We probably need to handle fixed point types specially here.
+ if (Opc != BO_Shl || LHSExprType->isFixedPointType())
return;
// When left shifting an ICE which is signed, we can check for overflow which
@@ -10784,7 +10941,9 @@ QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
QualType RHSType = RHS.get()->getType();
// C99 6.5.7p2: Each of the operands shall have integer type.
- if (!LHSType->hasIntegerRepresentation() ||
+ // Embedded-C 4.1.6.2.2: The LHS may also be fixed-point.
+ if ((!LHSType->isFixedPointOrIntegerType() &&
+ !LHSType->hasIntegerRepresentation()) ||
!RHSType->hasIntegerRepresentation())
return InvalidOperands(Loc, LHS, RHS);
@@ -13632,7 +13791,7 @@ static std::pair<ExprResult, ExprResult>
CorrectDelayedTyposInBinOp(Sema &S, BinaryOperatorKind Opc, Expr *LHSExpr,
Expr *RHSExpr) {
ExprResult LHS = LHSExpr, RHS = RHSExpr;
- if (!S.getLangOpts().CPlusPlus) {
+ if (!S.Context.isDependenceAllowed()) {
// 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.
@@ -13889,9 +14048,10 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
// float vectors and truncating the result back to half vector. For now, we do
// this only when HalfArgsAndReturn is set (that is, when the target is arm or
// arm64).
- assert(isVector(RHS.get()->getType(), Context.HalfTy) ==
- isVector(LHS.get()->getType(), Context.HalfTy) &&
- "both sides are half vectors or neither sides are");
+ assert(
+ (Opc == BO_Comma || isVector(RHS.get()->getType(), Context.HalfTy) ==
+ isVector(LHS.get()->getType(), Context.HalfTy)) &&
+ "both sides are half vectors or neither sides are");
ConvertHalfVec =
needsConversionOfHalfVec(ConvertHalfVec, Context, LHS.get(), RHS.get());
@@ -14169,6 +14329,19 @@ ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
return BuildBinOp(S, TokLoc, Opc, LHSExpr, RHSExpr);
}
+void Sema::LookupBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc,
+ UnresolvedSetImpl &Functions) {
+ OverloadedOperatorKind OverOp = BinaryOperator::getOverloadedOperator(Opc);
+ if (OverOp != OO_None && OverOp != OO_Equal)
+ LookupOverloadedOperatorName(OverOp, S, Functions);
+
+ // In C++20 onwards, we may have a second operator to look up.
+ if (getLangOpts().CPlusPlus20) {
+ if (OverloadedOperatorKind ExtraOp = getRewrittenOverloadedOperator(OverOp))
+ LookupOverloadedOperatorName(ExtraOp, S, Functions);
+ }
+}
+
/// Build an overloaded binary operator expression in the given scope.
static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc,
BinaryOperatorKind Opc,
@@ -14188,23 +14361,9 @@ static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc,
break;
}
- // Find all of the overloaded operators visible from this
- // point. We perform both an operator-name lookup from the local
- // scope and an argument-dependent lookup based on the types of
- // the arguments.
+ // Find all of the overloaded operators visible from this point.
UnresolvedSet<16> Functions;
- OverloadedOperatorKind OverOp
- = BinaryOperator::getOverloadedOperator(Opc);
- if (Sc && OverOp != OO_None && OverOp != OO_Equal)
- S.LookupOverloadedOperatorName(OverOp, Sc, LHS->getType(),
- RHS->getType(), Functions);
-
- // In C++20 onwards, we may have a second operator to look up.
- if (S.getLangOpts().CPlusPlus20) {
- if (OverloadedOperatorKind ExtraOp = getRewrittenOverloadedOperator(OverOp))
- S.LookupOverloadedOperatorName(ExtraOp, Sc, LHS->getType(),
- RHS->getType(), Functions);
- }
+ S.LookupBinOp(Sc, OpLoc, Opc, Functions);
// Build the (potentially-overloaded, potentially-dependent)
// binary operation.
@@ -14313,6 +14472,47 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
}
+ if (getLangOpts().RecoveryAST &&
+ (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent())) {
+ assert(!getLangOpts().CPlusPlus);
+ assert((LHSExpr->containsErrors() || RHSExpr->containsErrors()) &&
+ "Should only occur in error-recovery path.");
+ if (BinaryOperator::isCompoundAssignmentOp(Opc))
+ // C [6.15.16] p3:
+ // An assignment expression has the value of the left operand after the
+ // assignment, but is not an lvalue.
+ return CompoundAssignOperator::Create(
+ Context, LHSExpr, RHSExpr, Opc,
+ LHSExpr->getType().getUnqualifiedType(), VK_RValue, OK_Ordinary,
+ OpLoc, CurFPFeatureOverrides());
+ QualType ResultType;
+ switch (Opc) {
+ case BO_Assign:
+ ResultType = LHSExpr->getType().getUnqualifiedType();
+ break;
+ case BO_LT:
+ case BO_GT:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ:
+ case BO_NE:
+ case BO_LAnd:
+ case BO_LOr:
+ // These operators have a fixed result type regardless of operands.
+ ResultType = Context.IntTy;
+ break;
+ case BO_Comma:
+ ResultType = RHSExpr->getType();
+ break;
+ default:
+ ResultType = Context.DependentTy;
+ break;
+ }
+ return BinaryOperator::Create(Context, LHSExpr, RHSExpr, Opc, ResultType,
+ VK_RValue, OK_Ordinary, OpLoc,
+ CurFPFeatureOverrides());
+ }
+
// Build a built-in binary operation.
return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr);
}
@@ -14540,7 +14740,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
OpLoc, CanOverflow, CurFPFeatureOverrides());
if (Opc == UO_Deref && UO->getType()->hasAttr(attr::NoDeref) &&
- !isa<ArrayType>(UO->getType().getDesugaredType(Context)))
+ !isa<ArrayType>(UO->getType().getDesugaredType(Context)) &&
+ !isUnevaluatedContext())
ExprEvalContexts.back().PossibleDerefs.insert(UO);
// Convert the result back to a half vector.
@@ -14620,15 +14821,11 @@ ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
if (getLangOpts().CPlusPlus && Input->getType()->isOverloadableType() &&
UnaryOperator::getOverloadedOperator(Opc) != OO_None &&
!(Opc == UO_AddrOf && isQualifiedMemberAccess(Input))) {
- // Find all of the overloaded operators visible from this
- // point. We perform both an operator-name lookup from the local
- // scope and an argument-dependent lookup based on the types of
- // the arguments.
+ // Find all of the overloaded operators visible from this point.
UnresolvedSet<16> Functions;
OverloadedOperatorKind OverOp = UnaryOperator::getOverloadedOperator(Opc);
if (S && OverOp != OO_None)
- LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(),
- Functions);
+ LookupOverloadedOperatorName(OverOp, S, Functions);
return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, Input);
}
@@ -14935,9 +15132,8 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
} else {
// The conditional expression is required to be a constant expression.
llvm::APSInt condEval(32);
- ExprResult CondICE
- = VerifyIntegerConstantExpression(CondExpr, &condEval,
- diag::err_typecheck_choose_expr_requires_constant, false);
+ ExprResult CondICE = VerifyIntegerConstantExpression(
+ CondExpr, &condEval, diag::err_typecheck_choose_expr_requires_constant);
if (CondICE.isInvalid())
return ExprError();
CondExpr = CondICE.get();
@@ -14993,7 +15189,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
Scope *CurScope) {
assert(ParamInfo.getIdentifier() == nullptr &&
"block-id should have no identifier!");
- assert(ParamInfo.getContext() == DeclaratorContext::BlockLiteralContext);
+ assert(ParamInfo.getContext() == DeclaratorContext::BlockLiteral);
BlockScopeInfo *CurBlock = getCurBlock();
TypeSourceInfo *Sig = GetTypeForDeclarator(ParamInfo, CurScope);
@@ -15041,10 +15237,10 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
CurBlock->TheDecl->setSignatureAsWritten(Sig);
CurBlock->FunctionType = T;
- const FunctionType *Fn = T->getAs<FunctionType>();
+ const auto *Fn = T->castAs<FunctionType>();
QualType RetTy = Fn->getReturnType();
bool isVariadic =
- (isa<FunctionProtoType>(Fn) && cast<FunctionProtoType>(Fn)->isVariadic());
+ (isa<FunctionProtoType>(Fn) && cast<FunctionProtoType>(Fn)->isVariadic());
CurBlock->TheDecl->setIsVariadic(isVariadic);
@@ -15207,10 +15403,6 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
PopDeclContext();
- // Pop the block scope now but keep it alive to the end of this function.
- AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
- PoppedFunctionScopePtr ScopeRAII = PopFunctionScopeInfo(&WP, BD, BlockTy);
-
// Set the captured variables on the block.
SmallVector<BlockDecl::Capture, 4> Captures;
for (Capture &Cap : BSI->Captures) {
@@ -15278,6 +15470,10 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
}
BD->setCaptures(Context, Captures, BSI->CXXThisCaptureIndex != 0);
+ // Pop the block scope now but keep it alive to the end of this function.
+ AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
+ PoppedFunctionScopePtr ScopeRAII = PopFunctionScopeInfo(&WP, BD, BlockTy);
+
BlockExpr *Result = new (Context) BlockExpr(BD, BlockTy);
// If the block isn't obviously global, i.e. it captures anything at
@@ -15543,7 +15739,6 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
bool CheckInferredResultType = false;
bool isInvalid = false;
unsigned DiagKind = 0;
- FixItHint Hint;
ConversionFixItGenerator ConvHints;
bool MayHaveConvFixit = false;
bool MayHaveFunctionDiff = false;
@@ -15596,10 +15791,9 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
}
CheckInferredResultType = DstType->isObjCObjectPointerType() &&
SrcType->isObjCObjectPointerType();
- if (Hint.isNull() && !CheckInferredResultType) {
+ if (!CheckInferredResultType) {
ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
- }
- else if (CheckInferredResultType) {
+ } else if (CheckInferredResultType) {
SrcType = SrcType.getUnqualifiedType();
DstType = DstType.getUnqualifiedType();
}
@@ -15767,14 +15961,22 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
else
FDiag << FirstType << SecondType << Action << SrcExpr->getSourceRange();
+ if (DiagKind == diag::ext_typecheck_convert_incompatible_pointer_sign ||
+ DiagKind == diag::err_typecheck_convert_incompatible_pointer_sign) {
+ auto isPlainChar = [](const clang::Type *Type) {
+ return Type->isSpecificBuiltinType(BuiltinType::Char_S) ||
+ Type->isSpecificBuiltinType(BuiltinType::Char_U);
+ };
+ FDiag << (isPlainChar(FirstType->getPointeeOrArrayElementType()) ||
+ isPlainChar(SecondType->getPointeeOrArrayElementType()));
+ }
+
// If we can fix the conversion, suggest the FixIts.
- assert(ConvHints.isNull() || Hint.isNull());
if (!ConvHints.isNull()) {
for (FixItHint &H : ConvHints.Hints)
FDiag << H;
- } else {
- FDiag << Hint;
}
+
if (MayHaveConvFixit) { FDiag << (unsigned) (ConvHints.Kind); }
if (MayHaveFunctionDiff)
@@ -15803,21 +16005,27 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
}
ExprResult Sema::VerifyIntegerConstantExpression(Expr *E,
- llvm::APSInt *Result) {
+ llvm::APSInt *Result,
+ AllowFoldKind CanFold) {
class SimpleICEDiagnoser : public VerifyICEDiagnoser {
public:
- void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override {
- S.Diag(Loc, diag::err_expr_not_ice) << S.LangOpts.CPlusPlus << SR;
+ SemaDiagnosticBuilder diagnoseNotICEType(Sema &S, SourceLocation Loc,
+ QualType T) override {
+ return S.Diag(Loc, diag::err_ice_not_integral)
+ << T << S.LangOpts.CPlusPlus;
+ }
+ SemaDiagnosticBuilder diagnoseNotICE(Sema &S, SourceLocation Loc) override {
+ return S.Diag(Loc, diag::err_expr_not_ice) << S.LangOpts.CPlusPlus;
}
} Diagnoser;
- return VerifyIntegerConstantExpression(E, Result, Diagnoser);
+ return VerifyIntegerConstantExpression(E, Result, Diagnoser, CanFold);
}
ExprResult Sema::VerifyIntegerConstantExpression(Expr *E,
llvm::APSInt *Result,
unsigned DiagID,
- bool AllowFold) {
+ AllowFoldKind CanFold) {
class IDDiagnoser : public VerifyICEDiagnoser {
unsigned DiagID;
@@ -15825,23 +16033,29 @@ ExprResult Sema::VerifyIntegerConstantExpression(Expr *E,
IDDiagnoser(unsigned DiagID)
: VerifyICEDiagnoser(DiagID == 0), DiagID(DiagID) { }
- void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override {
- S.Diag(Loc, DiagID) << SR;
+ SemaDiagnosticBuilder diagnoseNotICE(Sema &S, SourceLocation Loc) override {
+ return S.Diag(Loc, DiagID);
}
} Diagnoser(DiagID);
- return VerifyIntegerConstantExpression(E, Result, Diagnoser, AllowFold);
+ return VerifyIntegerConstantExpression(E, Result, Diagnoser, CanFold);
+}
+
+Sema::SemaDiagnosticBuilder
+Sema::VerifyICEDiagnoser::diagnoseNotICEType(Sema &S, SourceLocation Loc,
+ QualType T) {
+ return diagnoseNotICE(S, Loc);
}
-void Sema::VerifyICEDiagnoser::diagnoseFold(Sema &S, SourceLocation Loc,
- SourceRange SR) {
- S.Diag(Loc, diag::ext_expr_not_ice) << SR << S.LangOpts.CPlusPlus;
+Sema::SemaDiagnosticBuilder
+Sema::VerifyICEDiagnoser::diagnoseFold(Sema &S, SourceLocation Loc) {
+ return S.Diag(Loc, diag::ext_expr_not_ice) << S.LangOpts.CPlusPlus;
}
ExprResult
Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
VerifyICEDiagnoser &Diagnoser,
- bool AllowFold) {
+ AllowFoldKind CanFold) {
SourceLocation DiagLoc = E->getBeginLoc();
if (getLangOpts().CPlusPlus11) {
@@ -15852,14 +16066,16 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
// unscoped enumeration type
ExprResult Converted;
class CXX11ConvertDiagnoser : public ICEConvertDiagnoser {
+ VerifyICEDiagnoser &BaseDiagnoser;
public:
- CXX11ConvertDiagnoser(bool Silent)
- : ICEConvertDiagnoser(/*AllowScopedEnumerations*/false,
- Silent, true) {}
+ CXX11ConvertDiagnoser(VerifyICEDiagnoser &BaseDiagnoser)
+ : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false,
+ BaseDiagnoser.Suppress, true),
+ BaseDiagnoser(BaseDiagnoser) {}
SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
QualType T) override {
- return S.Diag(Loc, diag::err_ice_not_integral) << T;
+ return BaseDiagnoser.diagnoseNotICEType(S, Loc, T);
}
SemaDiagnosticBuilder diagnoseIncomplete(
@@ -15893,7 +16109,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
llvm_unreachable("conversion functions are permitted");
}
- } ConvertDiagnoser(Diagnoser.Suppress);
+ } ConvertDiagnoser(Diagnoser);
Converted = PerformContextualImplicitConversion(DiagLoc, E,
ConvertDiagnoser);
@@ -15905,7 +16121,8 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
} else if (!E->getType()->isIntegralOrUnscopedEnumerationType()) {
// An ICE must be of integral or unscoped enumeration type.
if (!Diagnoser.Suppress)
- Diagnoser.diagnoseNotICE(*this, DiagLoc, E->getSourceRange());
+ Diagnoser.diagnoseNotICEType(*this, DiagLoc, E->getType())
+ << E->getSourceRange();
return ExprError();
}
@@ -15956,9 +16173,9 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
Notes.clear();
}
- if (!Folded || !AllowFold) {
+ if (!Folded || !CanFold) {
if (!Diagnoser.Suppress) {
- Diagnoser.diagnoseNotICE(*this, DiagLoc, E->getSourceRange());
+ Diagnoser.diagnoseNotICE(*this, DiagLoc) << E->getSourceRange();
for (const PartialDiagnosticAt &Note : Notes)
Diag(Note.first, Note.second);
}
@@ -15966,7 +16183,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
return ExprError();
}
- Diagnoser.diagnoseFold(*this, DiagLoc, E->getSourceRange());
+ Diagnoser.diagnoseFold(*this, DiagLoc) << E->getSourceRange();
for (const PartialDiagnosticAt &Note : Notes)
Diag(Note.first, Note.second);
@@ -16148,8 +16365,8 @@ static void EvaluateAndDiagnoseImmediateInvocation(
Expr::EvalResult Eval;
Eval.Diag = &Notes;
ConstantExpr *CE = Candidate.getPointer();
- bool Result = CE->EvaluateAsConstantExpr(Eval, Expr::EvaluateForCodeGen,
- SemaRef.getASTContext(), true);
+ bool Result = CE->EvaluateAsConstantExpr(
+ Eval, SemaRef.getASTContext(), ConstantExprKind::ImmediateInvocation);
if (!Result || !Notes.empty()) {
Expr *InnerExpr = CE->getSubExpr()->IgnoreImplicit();
if (auto *FunctionalCast = dyn_cast<CXXFunctionalCastExpr>(InnerExpr))
@@ -16532,8 +16749,13 @@ static OdrUseContext isOdrUseContext(Sema &SemaRef) {
}
static bool isImplicitlyDefinableConstexprFunction(FunctionDecl *Func) {
- return Func->isConstexpr() &&
- (Func->isImplicitlyInstantiable() || !Func->isUserProvided());
+ if (!Func->isConstexpr())
+ return false;
+
+ if (Func->isImplicitlyInstantiable() || !Func->isUserProvided())
+ return true;
+ auto *CCD = dyn_cast<CXXConstructorDecl>(Func);
+ return CCD && CCD->getInheritedConstructor();
}
/// Mark a function referenced, and check whether it is odr-used
@@ -16686,7 +16908,11 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
bool FirstInstantiation = PointOfInstantiation.isInvalid();
if (FirstInstantiation) {
PointOfInstantiation = Loc;
- Func->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+ if (auto *MSI = Func->getMemberSpecializationInfo())
+ MSI->setPointOfInstantiation(Loc);
+ // FIXME: Notify listener.
+ else
+ Func->setTemplateSpecializationKind(TSK, PointOfInstantiation);
} else if (TSK != TSK_ImplicitInstantiation) {
// Use the point of use as the point of instantiation, instead of the
// point of explicit instantiation (which we track as the actual point
@@ -16925,8 +17151,7 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var,
if (Var->getType()->isVariablyModifiedType() && IsBlock) {
if (Diagnose) {
S.Diag(Loc, diag::err_ref_vm_type);
- S.Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
+ S.Diag(Var->getLocation(), diag::note_previous_decl) << Var;
}
return false;
}
@@ -16938,10 +17163,8 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var,
if (IsBlock)
S.Diag(Loc, diag::err_ref_flexarray_type);
else
- S.Diag(Loc, diag::err_lambda_capture_flexarray_type)
- << Var->getDeclName();
- S.Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
+ S.Diag(Loc, diag::err_lambda_capture_flexarray_type) << Var;
+ S.Diag(Var->getLocation(), diag::note_previous_decl) << Var;
}
return false;
}
@@ -16951,10 +17174,8 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var,
// variables; they don't support the expected semantics.
if (HasBlocksAttr && (IsLambda || isa<CapturedRegionScopeInfo>(CSI))) {
if (Diagnose) {
- S.Diag(Loc, diag::err_capture_block_variable)
- << Var->getDeclName() << !IsLambda;
- S.Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
+ S.Diag(Loc, diag::err_capture_block_variable) << Var << !IsLambda;
+ S.Diag(Var->getLocation(), diag::note_previous_decl) << Var;
}
return false;
}
@@ -16985,8 +17206,7 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
if (!Invalid && !S.getLangOpts().OpenCL && CaptureType->isArrayType()) {
if (BuildAndDiagnose) {
S.Diag(Loc, diag::err_ref_array_type);
- S.Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
+ S.Diag(Var->getLocation(), diag::note_previous_decl) << Var;
Invalid = true;
} else {
return false;
@@ -16999,8 +17219,7 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
if (BuildAndDiagnose) {
S.Diag(Loc, diag::err_arc_autoreleasing_capture)
<< /*block*/ 0;
- S.Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
+ S.Diag(Var->getLocation(), diag::note_previous_decl) << Var;
Invalid = true;
} else {
return false;
@@ -17270,9 +17489,8 @@ bool Sema::tryCaptureVariable(
if (BuildAndDiagnose) {
LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);
if (LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None) {
- Diag(ExprLoc, diag::err_lambda_impcap) << Var->getDeclName();
- Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
+ Diag(ExprLoc, diag::err_lambda_impcap) << Var;
+ Diag(Var->getLocation(), diag::note_previous_decl) << Var;
Diag(LSI->Lambda->getBeginLoc(), diag::note_lambda_decl);
} else
diagnoseUncapturableValueReference(*this, ExprLoc, Var, DC);
@@ -17335,7 +17553,11 @@ bool Sema::tryCaptureVariable(
if (IsTargetCap || IsOpenMPPrivateDecl == OMPC_private ||
(IsGlobal && !IsGlobalCap)) {
Nested = !IsTargetCap;
+ bool HasConst = DeclRefType.isConstQualified();
DeclRefType = DeclRefType.getUnqualifiedType();
+ // Don't lose diagnostics about assignments to const.
+ if (HasConst)
+ DeclRefType.addConst();
CaptureType = Context.getLValueReferenceType(DeclRefType);
break;
}
@@ -17346,9 +17568,8 @@ bool Sema::tryCaptureVariable(
// No capture-default, and this is not an explicit capture
// so cannot capture this variable.
if (BuildAndDiagnose) {
- Diag(ExprLoc, diag::err_lambda_impcap) << Var->getDeclName();
- Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
+ Diag(ExprLoc, diag::err_lambda_impcap) << Var;
+ Diag(Var->getLocation(), diag::note_previous_decl) << Var;
if (cast<LambdaScopeInfo>(CSI)->Lambda)
Diag(cast<LambdaScopeInfo>(CSI)->Lambda->getBeginLoc(),
diag::note_lambda_decl);
@@ -17868,6 +18089,24 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
if (Var->isInvalidDecl())
return;
+ // Record a CUDA/HIP static device/constant variable if it is referenced
+ // by host code. This is done conservatively, when the variable is referenced
+ // in any of the following contexts:
+ // - a non-function context
+ // - a host function
+ // - a host device function
+ // This also requires the reference of the static device/constant variable by
+ // host code to be visible in the device compilation for the compiler to be
+ // able to externalize the static device/constant variable.
+ if (SemaRef.getASTContext().mayExternalizeStaticVar(Var)) {
+ auto *CurContext = SemaRef.CurContext;
+ if (!CurContext || !isa<FunctionDecl>(CurContext) ||
+ cast<FunctionDecl>(CurContext)->hasAttr<CUDAHostAttr>() ||
+ (!cast<FunctionDecl>(CurContext)->hasAttr<CUDADeviceAttr>() &&
+ !cast<FunctionDecl>(CurContext)->hasAttr<CUDAGlobalAttr>()))
+ SemaRef.getASTContext().CUDAStaticDeviceVarReferencedByHost.insert(Var);
+ }
+
auto *MSI = Var->getMemberSpecializationInfo();
TemplateSpecializationKind TSK = MSI ? MSI->getTemplateSpecializationKind()
: Var->getTemplateSpecializationKind();
@@ -17887,8 +18126,6 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
bool NeedDefinition =
OdrUse == OdrUseContext::Used || NeededForConstantEvaluation;
- VarTemplateSpecializationDecl *VarSpec =
- dyn_cast<VarTemplateSpecializationDecl>(Var);
assert(!isa<VarTemplatePartialSpecializationDecl>(Var) &&
"Can't instantiate a partial template specialization.");
@@ -17919,34 +18156,33 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
PointOfInstantiation = Loc;
if (MSI)
MSI->setPointOfInstantiation(PointOfInstantiation);
+ // FIXME: Notify listener.
else
Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
}
- bool InstantiationDependent = false;
- bool IsNonDependent =
- VarSpec ? !TemplateSpecializationType::anyDependentTemplateArguments(
- VarSpec->getTemplateArgsInfo(), InstantiationDependent)
- : true;
-
- // Do not instantiate specializations that are still type-dependent.
- if (IsNonDependent) {
- if (UsableInConstantExpr) {
- // Do not defer instantiations of variables that could be used in a
- // constant expression.
- SemaRef.runWithSufficientStackSpace(PointOfInstantiation, [&] {
- SemaRef.InstantiateVariableDefinition(PointOfInstantiation, Var);
- });
- } else if (FirstInstantiation ||
- isa<VarTemplateSpecializationDecl>(Var)) {
- // FIXME: For a specialization of a variable template, we don't
- // distinguish between "declaration and type implicitly instantiated"
- // and "implicit instantiation of definition requested", so we have
- // no direct way to avoid enqueueing the pending instantiation
- // multiple times.
- SemaRef.PendingInstantiations
- .push_back(std::make_pair(Var, PointOfInstantiation));
- }
+ if (UsableInConstantExpr) {
+ // Do not defer instantiations of variables that could be used in a
+ // constant expression.
+ SemaRef.runWithSufficientStackSpace(PointOfInstantiation, [&] {
+ SemaRef.InstantiateVariableDefinition(PointOfInstantiation, Var);
+ });
+
+ // Re-set the member to trigger a recomputation of the dependence bits
+ // for the expression.
+ if (auto *DRE = dyn_cast_or_null<DeclRefExpr>(E))
+ DRE->setDecl(DRE->getDecl());
+ else if (auto *ME = dyn_cast_or_null<MemberExpr>(E))
+ ME->setMemberDecl(ME->getMemberDecl());
+ } else if (FirstInstantiation ||
+ isa<VarTemplateSpecializationDecl>(Var)) {
+ // FIXME: For a specialization of a variable template, we don't
+ // distinguish between "declaration and type implicitly instantiated"
+ // and "implicit instantiation of definition requested", so we have
+ // no direct way to avoid enqueueing the pending instantiation
+ // multiple times.
+ SemaRef.PendingInstantiations
+ .push_back(std::make_pair(Var, PointOfInstantiation));
}
}
}
@@ -18072,6 +18308,9 @@ static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
}
/// Perform reference-marking and odr-use handling for a DeclRefExpr.
+///
+/// Note, this may change the dependence of the DeclRefExpr, and so needs to be
+/// handled with care if the DeclRefExpr is not newly-created.
void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) {
// TODO: update this with DR# once a defect report is filed.
// C++11 defect. The address of a pure member should not be an ODR use, even
@@ -18198,6 +18437,10 @@ public:
if (VD->hasLocalStorage())
return;
}
+
+ // FIXME: This can trigger the instantiation of the initializer of a
+ // variable, which can cause the expression to become value-dependent
+ // or error-dependent. Do we need to propagate the new dependence bits?
S.MarkDeclRefReferenced(E);
}
@@ -18312,7 +18555,7 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
}
S.Diag(Loc, diag::err_call_function_incomplete_return)
- << CE->getSourceRange() << FD->getDeclName() << T;
+ << CE->getSourceRange() << FD << T;
S.Diag(FD->getLocation(), diag::note_entity_declared_at)
<< FD->getDeclName();
}
@@ -18462,9 +18705,12 @@ Sema::ConditionResult Sema::ActOnCondition(Scope *S, SourceLocation Loc,
Cond = CheckSwitchCondition(Loc, SubExpr);
break;
}
- if (Cond.isInvalid())
- return ConditionError();
-
+ if (Cond.isInvalid()) {
+ Cond = CreateRecoveryExpr(SubExpr->getBeginLoc(), SubExpr->getEndLoc(),
+ {SubExpr});
+ if (!Cond.get())
+ return ConditionError();
+ }
// FIXME: FullExprArg doesn't have an invalid bit, so check nullness instead.
FullExprArg FullExpr = MakeFullExpr(Cond.get(), Loc);
if (!FullExpr.get())
@@ -18853,7 +19099,7 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) {
S.Context, FD->getDeclContext(), Loc, Loc,
FD->getNameInfo().getName(), DestType, FD->getTypeSourceInfo(),
SC_None, false /*isInlineSpecified*/, FD->hasPrototype(),
- /*ConstexprKind*/ CSK_unspecified);
+ /*ConstexprKind*/ ConstexprSpecKind::Unspecified);
if (FD->getQualifier())
NewFD->setQualifierInfo(FD->getQualifierLoc());
@@ -19001,7 +19247,7 @@ static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) {
/// Check for operands with placeholder types and complain if found.
/// Returns ExprError() if there was an error and no recovery was possible.
ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
- if (!getLangOpts().CPlusPlus) {
+ if (!Context.isDependenceAllowed()) {
// 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.
@@ -19078,7 +19324,8 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
CK_BuiltinFnToFnPtr)
.get();
return CallExpr::Create(Context, E, /*Args=*/{}, Context.IntTy,
- VK_RValue, SourceLocation());
+ VK_RValue, SourceLocation(),
+ FPOptionsOverride());
}
}
@@ -19115,6 +19362,9 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
#define SVE_TYPE(Name, Id, SingletonId) \
case BuiltinType::Id:
#include "clang/Basic/AArch64SVEACLETypes.def"
+#define PPC_VECTOR_TYPE(Name, Id, Size) \
+ case BuiltinType::Id:
+#include "clang/Basic/PPCTypes.def"
#define BUILTIN_TYPE(Id, SingletonId) case BuiltinType::Id:
#define PLACEHOLDER_TYPE(Id, SingletonId)
#include "clang/AST/BuiltinTypes.def"
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index d885920b6c14..d91db60f17a0 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -172,7 +172,7 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
bool Failed = false;
llvm::SmallVector<NamedDecl*, 8> FoundDecls;
- llvm::SmallSet<CanonicalDeclPtr<Decl>, 8> FoundDeclSet;
+ llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 8> FoundDeclSet;
// If we have an object type, it's because we are in a
// pseudo-destructor-expression or a member access expression, and
@@ -663,7 +663,16 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
}
// The operand is an expression.
- return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc);
+ ExprResult Result =
+ BuildCXXTypeId(TypeInfoType, OpLoc, (Expr *)TyOrExpr, RParenLoc);
+
+ if (!getLangOpts().RTTIData && !Result.isInvalid())
+ if (auto *CTE = dyn_cast<CXXTypeidExpr>(Result.get()))
+ if (CTE->isPotentiallyEvaluated() && !CTE->isMostDerived(Context))
+ Diag(OpLoc, diag::warn_no_typeid_with_rtti_disabled)
+ << (getDiagnostics().getDiagnosticOptions().getFormat() ==
+ DiagnosticOptions::MSVC);
+ return Result;
}
/// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to
@@ -875,6 +884,10 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
Ex = Res.get();
}
+ // PPC MMA non-pointer types are not allowed as throw expr types.
+ if (Ex && Context.getTargetInfo().getTriple().isPPC64())
+ CheckPPCMMAType(Ex->getType(), Ex->getBeginLoc());
+
return new (Context)
CXXThrowExpr(Ex, Context.VoidTy, OpLoc, IsThrownVarInScope);
}
@@ -1389,6 +1402,9 @@ Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep,
if (!Result.isInvalid() && Result.get()->isInstantiationDependent() &&
!Result.get()->isTypeDependent())
Result = CorrectDelayedTyposInExpr(Result.get());
+ else if (Result.isInvalid())
+ Result = CreateRecoveryExpr(TInfo->getTypeLoc().getBeginLoc(),
+ RParenOrBraceLoc, exprs, Ty);
return Result;
}
@@ -1401,16 +1417,6 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
QualType Ty = TInfo->getType();
SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc();
- if (Ty->isDependentType() || CallExpr::hasAnyTypeDependentArguments(Exprs)) {
- // FIXME: CXXUnresolvedConstructExpr does not model list-initialization
- // directly. We work around this by dropping the locations of the braces.
- SourceRange Locs = ListInitialization
- ? SourceRange()
- : SourceRange(LParenOrBraceLoc, RParenOrBraceLoc);
- return CXXUnresolvedConstructExpr::Create(Context, TInfo, Locs.getBegin(),
- Exprs, Locs.getEnd());
- }
-
assert((!ListInitialization ||
(Exprs.size() == 1 && isa<InitListExpr>(Exprs[0]))) &&
"List initialization must have initializer list as expression.");
@@ -1439,6 +1445,17 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
Entity = InitializedEntity::InitializeTemporary(TInfo, Ty);
}
+ if (Ty->isDependentType() || CallExpr::hasAnyTypeDependentArguments(Exprs)) {
+ // FIXME: CXXUnresolvedConstructExpr does not model list-initialization
+ // directly. We work around this by dropping the locations of the braces.
+ SourceRange Locs = ListInitialization
+ ? SourceRange()
+ : SourceRange(LParenOrBraceLoc, RParenOrBraceLoc);
+ return CXXUnresolvedConstructExpr::Create(Context, Ty.getNonReferenceType(),
+ TInfo, Locs.getBegin(), Exprs,
+ Locs.getEnd());
+ }
+
// C++ [expr.type.conv]p1:
// If the expression list is a parenthesized single expression, the type
// conversion expression is equivalent (in definedness, and if defined in
@@ -1500,7 +1517,8 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
: SourceRange(LParenOrBraceLoc, RParenOrBraceLoc);
Result = CXXFunctionalCastExpr::Create(
Context, ResultType, Expr::getValueKindForType(Ty), TInfo, CK_NoOp,
- Result.get(), /*Path=*/nullptr, Locs.getBegin(), Locs.getEnd());
+ Result.get(), /*Path=*/nullptr, CurFPFeatureOverrides(),
+ Locs.getBegin(), Locs.getEnd());
}
return Result;
@@ -1509,9 +1527,24 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
bool Sema::isUsualDeallocationFunction(const CXXMethodDecl *Method) {
// [CUDA] Ignore this function, if we can't call it.
const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext);
- if (getLangOpts().CUDA &&
- IdentifyCUDAPreference(Caller, Method) <= CFP_WrongSide)
- return false;
+ if (getLangOpts().CUDA) {
+ auto CallPreference = IdentifyCUDAPreference(Caller, Method);
+ // If it's not callable at all, it's not the right function.
+ if (CallPreference < CFP_WrongSide)
+ return false;
+ if (CallPreference == CFP_WrongSide) {
+ // Maybe. We have to check if there are better alternatives.
+ DeclContext::lookup_result R =
+ Method->getDeclContext()->lookup(Method->getDeclName());
+ for (const auto *D : R) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (IdentifyCUDAPreference(Caller, FD) > CFP_WrongSide)
+ return false;
+ }
+ }
+ // We've found no better variants.
+ }
+ }
SmallVector<const FunctionDecl*, 4> PreventedBy;
bool Result = Method->isUsualDeallocationFunction(PreventedBy);
@@ -1753,22 +1786,22 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
DeclaratorChunk::ArrayTypeInfo &Array = D.getTypeObject(I).Arr;
if (Expr *NumElts = (Expr *)Array.NumElts) {
if (!NumElts->isTypeDependent() && !NumElts->isValueDependent()) {
+ // FIXME: GCC permits constant folding here. We should either do so consistently
+ // or not do so at all, rather than changing behavior in C++14 onwards.
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.
- unsigned IntWidth = Context.getTargetInfo().getIntWidth();
- assert(IntWidth && "Builtin type of size 0?");
- llvm::APSInt Value(IntWidth);
+ llvm::APSInt Value(Context.getIntWidth(Context.getSizeType()));
Array.NumElts
= CheckConvertedConstantExpression(NumElts, Context.getSizeType(), Value,
- CCEK_NewExpr)
+ CCEK_ArrayBound)
.get();
} else {
- Array.NumElts
- = VerifyIntegerConstantExpression(NumElts, nullptr,
- diag::err_new_array_nonconst)
- .get();
+ Array.NumElts =
+ VerifyIntegerConstantExpression(
+ NumElts, nullptr, diag::err_new_array_nonconst, AllowFold)
+ .get();
}
if (!Array.NumElts)
return ExprError();
@@ -1832,12 +1865,13 @@ void Sema::diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD,
const llvm::Triple &T = getASTContext().getTargetInfo().getTriple();
StringRef OSName = AvailabilityAttr::getPlatformNameSourceSpelling(
getASTContext().getTargetInfo().getPlatformName());
+ VersionTuple OSVersion = alignedAllocMinVersion(T.getOS());
OverloadedOperatorKind Kind = FD.getDeclName().getCXXOverloadedOperator();
bool IsDelete = Kind == OO_Delete || Kind == OO_Array_Delete;
Diag(Loc, diag::err_aligned_allocation_unavailable)
<< IsDelete << FD.getType().getAsString() << OSName
- << alignedAllocMinVersion(T.getOS()).getAsString();
+ << OSVersion.getAsString() << OSVersion.empty();
Diag(Loc, diag::note_silence_aligned_allocation_unavailable);
}
}
@@ -2073,29 +2107,29 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// per CWG1464. Otherwise, if it's not a constant, we must have an
// unparenthesized array type.
if (!(*ArraySize)->isValueDependent()) {
- llvm::APSInt Value;
// We've already performed any required implicit conversion to integer or
// unscoped enumeration type.
// FIXME: Per CWG1464, we are required to check the value prior to
// converting to size_t. This will never find a negative array size in
// C++14 onwards, because Value is always unsigned here!
- if ((*ArraySize)->isIntegerConstantExpr(Value, Context)) {
- if (Value.isSigned() && Value.isNegative()) {
+ if (Optional<llvm::APSInt> Value =
+ (*ArraySize)->getIntegerConstantExpr(Context)) {
+ if (Value->isSigned() && Value->isNegative()) {
return ExprError(Diag((*ArraySize)->getBeginLoc(),
diag::err_typecheck_negative_array_size)
<< (*ArraySize)->getSourceRange());
}
if (!AllocType->isDependentType()) {
- unsigned ActiveSizeBits =
- ConstantArrayType::getNumAddressingBits(Context, AllocType, Value);
+ unsigned ActiveSizeBits = ConstantArrayType::getNumAddressingBits(
+ Context, AllocType, *Value);
if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context))
return ExprError(
Diag((*ArraySize)->getBeginLoc(), diag::err_array_too_large)
- << Value.toString(10) << (*ArraySize)->getSourceRange());
+ << Value->toString(10) << (*ArraySize)->getSourceRange());
}
- KnownArraySize = Value.getZExtValue();
+ KnownArraySize = Value->getZExtValue();
} else if (TypeIdParens.isValid()) {
// Can't have dynamic array size when the type-id is in parentheses.
Diag((*ArraySize)->getBeginLoc(), diag::ext_new_paren_array_nonconst)
@@ -2203,7 +2237,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
SizeTy, SourceLocation());
ImplicitCastExpr DesiredAlignment(ImplicitCastExpr::OnStack, AlignValT,
CK_IntegralCast, &AlignmentLiteral,
- VK_RValue);
+ VK_RValue, FPOptionsOverride());
// Adjust placement args by prepending conjured size and alignment exprs.
llvm::SmallVector<Expr *, 8> CallArgs;
@@ -2611,8 +2645,24 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
if (FoundDelete.isAmbiguous())
return true; // FIXME: clean up expressions?
+ // Filter out any destroying operator deletes. We can't possibly call such a
+ // function in this context, because we're handling the case where the object
+ // was not successfully constructed.
+ // FIXME: This is not covered by the language rules yet.
+ {
+ LookupResult::Filter Filter = FoundDelete.makeFilter();
+ while (Filter.hasNext()) {
+ auto *FD = dyn_cast<FunctionDecl>(Filter.next()->getUnderlyingDecl());
+ if (FD && FD->isDestroyingOperatorDelete())
+ Filter.erase();
+ }
+ Filter.done();
+ }
+
bool FoundGlobalDelete = FoundDelete.empty();
if (FoundDelete.empty()) {
+ FoundDelete.clear(LookupOrdinaryName);
+
if (DeleteScope == AFS_Class)
return true;
@@ -3914,7 +3964,8 @@ static ExprResult BuildCXXCastArgument(Sema &S,
// Record usage of conversion in an implicit cast.
Result = ImplicitCastExpr::Create(S.Context, Result.get()->getType(),
CK_UserDefinedConversion, Result.get(),
- nullptr, Result.get()->getValueKind());
+ nullptr, Result.get()->getValueKind(),
+ S.CurFPFeatureOverrides());
return S.MaybeBindToTemporary(Result.get());
}
@@ -4095,7 +4146,8 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
if (const AtomicType *FromAtomic = FromType->getAs<AtomicType>()) {
FromType = FromAtomic->getValueType().getUnqualifiedType();
From = ImplicitCastExpr::Create(Context, FromType, CK_AtomicToNonAtomic,
- From, /*BasePath=*/nullptr, VK_RValue);
+ From, /*BasePath=*/nullptr, VK_RValue,
+ FPOptionsOverride());
}
break;
@@ -4322,6 +4374,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
+ case ICK_SVE_Vector_Conversion:
+ From = ImpCastExprToType(From, ToType, CK_BitCast, VK_RValue,
+ /*BasePath=*/nullptr, CCK)
+ .get();
+ break;
+
case ICK_Vector_Splat: {
// Vector splat from any arithmetic type to a vector.
Expr *Elem = prepareVectorSplat(ToType, From).get();
@@ -5465,9 +5523,9 @@ static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT,
case ATT_ArrayExtent: {
llvm::APSInt Value;
uint64_t Dim;
- if (Self.VerifyIntegerConstantExpression(DimExpr, &Value,
- diag::err_dimension_expr_not_constant_integer,
- false).isInvalid())
+ if (Self.VerifyIntegerConstantExpression(
+ DimExpr, &Value, diag::err_dimension_expr_not_constant_integer)
+ .isInvalid())
return 0;
if (Value.isSigned() && Value.isNegative()) {
Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer)
@@ -6304,6 +6362,8 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// Similarly, attempt to find composite type of two objective-c pointers.
Composite = FindCompositeObjCPointerType(LHS, RHS, QuestionLoc);
+ if (LHS.isInvalid() || RHS.isInvalid())
+ return QualType();
if (!Composite.isNull())
return Composite;
@@ -6529,12 +6589,16 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
// FIXME: In C, we merge __strong and none to __strong at the top level.
if (Q1.getObjCGCAttr() == Q2.getObjCGCAttr())
Quals.setObjCGCAttr(Q1.getObjCGCAttr());
+ else if (T1->isVoidPointerType() || T2->isVoidPointerType())
+ assert(Steps.size() == 1);
else
return QualType();
// Mismatched lifetime qualifiers never compatibly include each other.
if (Q1.getObjCLifetime() == Q2.getObjCLifetime())
Quals.setObjCLifetime(Q1.getObjCLifetime());
+ else if (T1->isVoidPointerType() || T2->isVoidPointerType())
+ assert(Steps.size() == 1);
else
return QualType();
@@ -6833,7 +6897,7 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) {
CastKind ck = (ReturnsRetained ? CK_ARCConsumeObject
: CK_ARCReclaimReturnedObject);
return ImplicitCastExpr::Create(Context, E->getType(), ck, E, nullptr,
- VK_RValue);
+ VK_RValue, FPOptionsOverride());
}
if (E->getType().isDestructedType() == QualType::DK_nontrivial_c_struct)
@@ -7226,8 +7290,8 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
return Base;
}
-static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base,
- tok::TokenKind& OpKind, SourceLocation OpLoc) {
+static bool CheckArrow(Sema &S, QualType &ObjectType, Expr *&Base,
+ tok::TokenKind &OpKind, SourceLocation OpLoc) {
if (Base->hasPlaceholderType()) {
ExprResult result = S.CheckPlaceholderExpr(Base);
if (result.isInvalid()) return true;
@@ -7242,6 +7306,18 @@ static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base,
// Note that this is rather different from the normal handling for the
// arrow operator.
if (OpKind == tok::arrow) {
+ // The operator requires a prvalue, so perform lvalue conversions.
+ // Only do this if we might plausibly end with a pointer, as otherwise
+ // this was likely to be intended to be a '.'.
+ if (ObjectType->isPointerType() || ObjectType->isArrayType() ||
+ ObjectType->isFunctionType()) {
+ ExprResult BaseResult = S.DefaultFunctionArrayLvalueConversion(Base);
+ if (BaseResult.isInvalid())
+ return true;
+ Base = BaseResult.get();
+ ObjectType = Base->getType();
+ }
+
if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) {
ObjectType = Ptr->getPointeeType();
} else if (!Base->isTypeDependent()) {
@@ -7550,6 +7626,11 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc))
return ExprError();
+ if (DS.getTypeSpecType() == DeclSpec::TST_decltype_auto) {
+ Diag(DS.getTypeSpecTypeLoc(), diag::err_decltype_auto_invalid);
+ return true;
+ }
+
QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc(),
false);
@@ -7616,7 +7697,8 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
ResultType = ResultType.getNonLValueExprType(Context);
CXXMemberCallExpr *CE = CXXMemberCallExpr::Create(
- Context, ME, /*Args=*/{}, ResultType, VK, Exp.get()->getEndLoc());
+ Context, ME, /*Args=*/{}, ResultType, VK, Exp.get()->getEndLoc(),
+ CurFPFeatureOverrides());
if (CheckFunctionCall(Method, CE,
Method->getType()->castAs<FunctionProtoType>()))
@@ -7640,7 +7722,8 @@ ExprResult Sema::BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
Operand = R.get();
- if (!inTemplateInstantiation() && Operand->HasSideEffects(Context, false)) {
+ if (!inTemplateInstantiation() && !Operand->isInstantiationDependent() &&
+ 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);
@@ -7977,19 +8060,26 @@ class TransformTypos : public TreeTransform<TransformTypos> {
}
}
- /// 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.
+ /// Try to advance the typo correction state of the first unfinished TypoExpr.
+ /// We allow advancement of the correction stream by removing it from the
+ /// TransformCache which allows `TransformTypoExpr` to advance during the
+ /// next transformation attempt.
+ ///
+ /// Any substitution attempts for the previous TypoExprs (which must have been
+ /// finished) will need to be retried since it's possible that they will now
+ /// be invalid given the latest advancement.
+ ///
+ /// We need to be sure that we're making progress - it's possible that the
+ /// tree is so malformed that the transform never makes it to the
+ /// `TransformTypoExpr`.
+ ///
+ /// Returns true if there are any untried correction combinations.
bool CheckAndAdvanceTypoExprCorrectionStreams() {
for (auto TE : TypoExprs) {
auto &State = SemaRef.getTypoExprState(TE);
TransformCache.erase(TE);
+ if (!State.Consumer->hasMadeAnyCorrectionProgress())
+ return false;
if (!State.Consumer->finished())
return true;
State.Consumer->resetCorrectionStream();
@@ -8639,6 +8729,9 @@ Sema::ActOnRequiresExpr(SourceLocation RequiresKWLoc,
ArrayRef<ParmVarDecl *> LocalParameters,
ArrayRef<concepts::Requirement *> Requirements,
SourceLocation ClosingBraceLoc) {
- return RequiresExpr::Create(Context, RequiresKWLoc, Body, LocalParameters,
- Requirements, ClosingBraceLoc);
+ auto *RE = RequiresExpr::Create(Context, RequiresKWLoc, Body, LocalParameters,
+ Requirements, ClosingBraceLoc);
+ if (DiagnoseUnexpandedParameterPackInRequiresExpr(RE))
+ return ExprError();
+ return RE;
}
diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
index ebfc1ec4b974..f5afcb76fc96 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -231,12 +231,10 @@ static void diagnoseInstanceReference(Sema &SemaRef,
}
/// Builds an expression which might be an implicit member expression.
-ExprResult
-Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- LookupResult &R,
- const TemplateArgumentListInfo *TemplateArgs,
- const Scope *S) {
+ExprResult Sema::BuildPossibleImplicitMemberExpr(
+ const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
+ UnresolvedLookupExpr *AsULE) {
switch (ClassifyImplicitMemberAccess(*this, R)) {
case IMA_Instance:
return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true, S);
@@ -257,7 +255,7 @@ Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
case IMA_Unresolved_StaticContext:
if (TemplateArgs || TemplateKWLoc.isValid())
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs);
- return BuildDeclarationNameExpr(SS, R, false);
+ return AsULE ? AsULE : BuildDeclarationNameExpr(SS, R, false);
case IMA_Error_StaticContext:
case IMA_Error_Unrelated:
@@ -946,28 +944,6 @@ static bool IsInFnTryBlockHandler(const Scope *S) {
return false;
}
-VarDecl *
-Sema::getVarTemplateSpecialization(VarTemplateDecl *VarTempl,
- const TemplateArgumentListInfo *TemplateArgs,
- const DeclarationNameInfo &MemberNameInfo,
- SourceLocation TemplateKWLoc) {
- if (!TemplateArgs) {
- diagnoseMissingTemplateArguments(TemplateName(VarTempl),
- MemberNameInfo.getBeginLoc());
- return nullptr;
- }
-
- DeclResult VDecl = CheckVarTemplateId(VarTempl, TemplateKWLoc,
- MemberNameInfo.getLoc(), *TemplateArgs);
- if (VDecl.isInvalid())
- return nullptr;
- VarDecl *Var = cast<VarDecl>(VDecl.get());
- if (!Var->getTemplateSpecializationKind())
- Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation,
- MemberNameInfo.getLoc());
- return Var;
-}
-
ExprResult
Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
SourceLocation OpLoc, bool IsArrow,
@@ -1099,19 +1075,11 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
if (!BaseExpr) {
// If this is not an instance member, convert to a non-member access.
if (!MemberDecl->isCXXInstanceMember()) {
- // If this is a variable template, get the instantiated variable
- // declaration corresponding to the supplied template arguments
- // (while emitting diagnostics as necessary) that will be referenced
- // by this expression.
- assert((!TemplateArgs || isa<VarTemplateDecl>(MemberDecl)) &&
- "How did we get template arguments here sans a variable template");
- if (isa<VarTemplateDecl>(MemberDecl)) {
- MemberDecl = getVarTemplateSpecialization(
- cast<VarTemplateDecl>(MemberDecl), TemplateArgs,
- R.getLookupNameInfo(), TemplateKWLoc);
- if (!MemberDecl)
- return ExprError();
- }
+ // We might have a variable template specialization (or maybe one day a
+ // member concept-id).
+ if (TemplateArgs || TemplateKWLoc.isValid())
+ return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/false, TemplateArgs);
+
return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), MemberDecl,
FoundDecl, TemplateArgs);
}
@@ -1170,14 +1138,32 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
MemberNameInfo, Enum->getType(), VK_RValue,
OK_Ordinary);
}
+
if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) {
- if (VarDecl *Var = getVarTemplateSpecialization(
- VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc))
- return BuildMemberExpr(
- BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var, FoundDecl,
- /*HadMultipleCandidates=*/false, MemberNameInfo,
- Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary);
- return ExprError();
+ if (!TemplateArgs) {
+ diagnoseMissingTemplateArguments(TemplateName(VarTempl), MemberLoc);
+ return ExprError();
+ }
+
+ DeclResult VDecl = CheckVarTemplateId(VarTempl, TemplateKWLoc,
+ MemberNameInfo.getLoc(), *TemplateArgs);
+ if (VDecl.isInvalid())
+ return ExprError();
+
+ // Non-dependent member, but dependent template arguments.
+ if (!VDecl.get())
+ return ActOnDependentMemberExpr(
+ BaseExpr, BaseExpr->getType(), IsArrow, OpLoc, SS, TemplateKWLoc,
+ FirstQualifierInScope, MemberNameInfo, TemplateArgs);
+
+ VarDecl *Var = cast<VarDecl>(VDecl.get());
+ if (!Var->getTemplateSpecializationKind())
+ Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation, MemberLoc);
+
+ return BuildMemberExpr(
+ BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var, FoundDecl,
+ /*HadMultipleCandidates=*/false, MemberNameInfo,
+ Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary);
}
// We found something that we didn't expect. Complain.
@@ -1748,14 +1734,28 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
}
void Sema::CheckMemberAccessOfNoDeref(const MemberExpr *E) {
- QualType ResultTy = E->getType();
-
- // Do not warn on member accesses to arrays since this returns an array
- // lvalue and does not actually dereference memory.
- if (isa<ArrayType>(ResultTy))
+ if (isUnevaluatedContext())
return;
- if (E->isArrow()) {
+ QualType ResultTy = E->getType();
+
+ // Member accesses have four cases:
+ // 1: non-array member via "->": dereferences
+ // 2: non-array member via ".": nothing interesting happens
+ // 3: array member access via "->": nothing interesting happens
+ // (this returns an array lvalue and does not actually dereference memory)
+ // 4: array member access via ".": *adds* a layer of indirection
+ if (ResultTy->isArrayType()) {
+ if (!E->isArrow()) {
+ // This might be something like:
+ // (*structPtr).arrayMember
+ // which behaves roughly like:
+ // &(*structPtr).pointerMember
+ // in that the apparent dereference in the base expression does not
+ // actually happen.
+ CheckAddressOfNoDeref(E->getBase());
+ }
+ } else if (E->isArrow()) {
if (const auto *Ptr = dyn_cast<PointerType>(
E->getBase()->getType().getDesugaredType(Context))) {
if (Ptr->getPointeeType()->hasAttr(attr::NoDeref))
@@ -1810,6 +1810,14 @@ Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
Qualifiers Combined = BaseQuals + MemberQuals;
if (Combined != MemberQuals)
MemberType = Context.getQualifiedType(MemberType, Combined);
+
+ // Pick up NoDeref from the base in case we end up using AddrOf on the
+ // result. E.g. the expression
+ // &someNoDerefPtr->pointerMember
+ // should be a noderef pointer again.
+ if (BaseType->hasAttr(attr::NoDeref))
+ MemberType =
+ Context.getAttributedType(attr::NoDeref, MemberType, MemberType);
}
auto *CurMethod = dyn_cast<CXXMethodDecl>(CurContext);
@@ -1854,7 +1862,6 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
// If this is known to be an instance access, go ahead and build an
// implicit 'this' expression now.
- // 'this' expression now.
QualType ThisTy = getCurrentThisType();
assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'");
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index 228a1ec3ba1f..f5456ee0711e 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -1394,6 +1394,9 @@ ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId;
return true;
}
+ if (PDecl->isNonRuntimeProtocol())
+ Diag(ProtoLoc, diag::err_objc_non_runtime_protocol_in_protocol_expr)
+ << PDecl;
if (!PDecl->hasDefinition()) {
Diag(ProtoLoc, diag::err_atprotocol_protocol) << PDecl;
Diag(PDecl->getLocation(), diag::note_entity_declared_at) << PDecl;
@@ -1560,12 +1563,20 @@ QualType Sema::getMessageSendResultType(const Expr *Receiver,
// Map the nullability of the result into a table index.
unsigned receiverNullabilityIdx = 0;
- if (auto nullability = ReceiverType->getNullability(Context))
+ if (Optional<NullabilityKind> nullability =
+ ReceiverType->getNullability(Context)) {
+ if (*nullability == NullabilityKind::NullableResult)
+ nullability = NullabilityKind::Nullable;
receiverNullabilityIdx = 1 + static_cast<unsigned>(*nullability);
+ }
unsigned resultNullabilityIdx = 0;
- if (auto nullability = resultType->getNullability(Context))
+ if (Optional<NullabilityKind> nullability =
+ resultType->getNullability(Context)) {
+ if (*nullability == NullabilityKind::NullableResult)
+ nullability = NullabilityKind::Nullable;
resultNullabilityIdx = 1 + static_cast<unsigned>(*nullability);
+ }
// The table of nullability mappings, indexed by the receiver's nullability
// and then the result type's nullability.
@@ -2445,8 +2456,8 @@ static void applyCocoaAPICheck(Sema &S, const ObjCMessageExpr *Msg,
SourceManager &SM = S.SourceMgr;
edit::Commit ECommit(SM, S.LangOpts);
if (refactor(Msg,*S.NSAPIObj, ECommit)) {
- DiagnosticBuilder Builder = S.Diag(MsgLoc, DiagID)
- << Msg->getSelector() << Msg->getSourceRange();
+ auto Builder = S.Diag(MsgLoc, DiagID)
+ << Msg->getSelector() << Msg->getSourceRange();
// FIXME: Don't emit diagnostic at all if fixits are non-commitable.
if (!ECommit.isCommitable())
return;
@@ -3139,9 +3150,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
if (ReceiverType->isObjCClassType() && !isImplicit &&
!(Receiver->isObjCSelfExpr() && getLangOpts().ObjCAutoRefCount)) {
{
- DiagnosticBuilder Builder =
- Diag(Receiver->getExprLoc(),
- diag::err_messaging_class_with_direct_method);
+ auto Builder = Diag(Receiver->getExprLoc(),
+ diag::err_messaging_class_with_direct_method);
if (Receiver->isObjCSelfExpr()) {
Builder.AddFixItHint(FixItHint::CreateReplacement(
RecRange, Method->getClassInterface()->getName()));
@@ -3153,7 +3163,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
if (SuperLoc.isValid()) {
{
- DiagnosticBuilder Builder =
+ auto Builder =
Diag(SuperLoc, diag::err_messaging_super_with_direct_method);
if (ReceiverType->isObjCClassType()) {
Builder.AddFixItHint(FixItHint::CreateReplacement(
@@ -3736,15 +3746,11 @@ bool Sema::isKnownName(StringRef name) {
return LookupName(R, TUScope, false);
}
-static void addFixitForObjCARCConversion(Sema &S,
- DiagnosticBuilder &DiagB,
- Sema::CheckedConversionKind CCK,
- SourceLocation afterLParen,
- QualType castType,
- Expr *castExpr,
- Expr *realCast,
- const char *bridgeKeyword,
- const char *CFBridgeName) {
+template <typename DiagBuilderT>
+static void addFixitForObjCARCConversion(
+ Sema &S, DiagBuilderT &DiagB, Sema::CheckedConversionKind CCK,
+ SourceLocation afterLParen, QualType castType, Expr *castExpr,
+ Expr *realCast, const char *bridgeKeyword, const char *CFBridgeName) {
// We handle C-style and implicit casts here.
switch (CCK) {
case Sema::CCK_ImplicitConversion:
@@ -3921,9 +3927,9 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
assert(CreateRule != ACC_bottom && "This cast should already be accepted.");
if (CreateRule != ACC_plusOne)
{
- DiagnosticBuilder DiagB =
- (CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge)
- : S.Diag(noteLoc, diag::note_arc_cstyle_bridge);
+ auto DiagB = (CCK != Sema::CCK_OtherCast)
+ ? S.Diag(noteLoc, diag::note_arc_bridge)
+ : S.Diag(noteLoc, diag::note_arc_cstyle_bridge);
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
castType, castExpr, realCast, "__bridge ",
@@ -3931,12 +3937,12 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
}
if (CreateRule != ACC_plusZero)
{
- DiagnosticBuilder DiagB =
- (CCK == Sema::CCK_OtherCast && !br) ?
- S.Diag(noteLoc, diag::note_arc_cstyle_bridge_transfer) << castExprType :
- S.Diag(br ? castExpr->getExprLoc() : noteLoc,
- diag::note_arc_bridge_transfer)
- << castExprType << br;
+ auto DiagB = (CCK == Sema::CCK_OtherCast && !br)
+ ? S.Diag(noteLoc, diag::note_arc_cstyle_bridge_transfer)
+ << castExprType
+ : S.Diag(br ? castExpr->getExprLoc() : noteLoc,
+ diag::note_arc_bridge_transfer)
+ << castExprType << br;
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
castType, castExpr, realCast, "__bridge_transfer ",
@@ -3962,21 +3968,21 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
assert(CreateRule != ACC_bottom && "This cast should already be accepted.");
if (CreateRule != ACC_plusOne)
{
- DiagnosticBuilder DiagB =
- (CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge)
- : S.Diag(noteLoc, diag::note_arc_cstyle_bridge);
+ auto DiagB = (CCK != Sema::CCK_OtherCast)
+ ? S.Diag(noteLoc, diag::note_arc_bridge)
+ : S.Diag(noteLoc, diag::note_arc_cstyle_bridge);
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
castType, castExpr, realCast, "__bridge ",
nullptr);
}
if (CreateRule != ACC_plusZero)
{
- DiagnosticBuilder DiagB =
- (CCK == Sema::CCK_OtherCast && !br) ?
- S.Diag(noteLoc, diag::note_arc_cstyle_bridge_retained) << castType :
- S.Diag(br ? castExpr->getExprLoc() : noteLoc,
- diag::note_arc_bridge_retained)
- << castType << br;
+ auto DiagB = (CCK == Sema::CCK_OtherCast && !br)
+ ? S.Diag(noteLoc, diag::note_arc_cstyle_bridge_retained)
+ << castType
+ : S.Diag(br ? castExpr->getExprLoc() : noteLoc,
+ diag::note_arc_bridge_retained)
+ << castType << br;
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
castType, castExpr, realCast, "__bridge_retained ",
@@ -4462,8 +4468,8 @@ Sema::CheckObjCConversion(SourceRange castRange, QualType castType,
// If the result is +1, consume it here.
case ACC_plusOne:
castExpr = ImplicitCastExpr::Create(Context, castExpr->getType(),
- CK_ARCConsumeObject, castExpr,
- nullptr, VK_RValue);
+ CK_ARCConsumeObject, castExpr, nullptr,
+ VK_RValue, FPOptionsOverride());
Cleanup.setExprNeedsCleanups(true);
return ACR_okay;
}
@@ -4689,9 +4695,9 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc,
case OBC_BridgeRetained:
// Produce the object before casting it.
- SubExpr = ImplicitCastExpr::Create(Context, FromType,
- CK_ARCProduceObject,
- SubExpr, nullptr, VK_RValue);
+ SubExpr = ImplicitCastExpr::Create(Context, FromType, CK_ARCProduceObject,
+ SubExpr, nullptr, VK_RValue,
+ FPOptionsOverride());
break;
case OBC_BridgeTransfer: {
@@ -4730,7 +4736,7 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc,
if (MustConsume) {
Cleanup.setExprNeedsCleanups(true);
Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result,
- nullptr, VK_RValue);
+ nullptr, VK_RValue, FPOptionsOverride());
}
return Result;
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index eb07de65d266..f4493d84238d 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -141,6 +141,10 @@ static StringInitFailureKind IsStringInit(Expr *init, QualType declType,
return IsStringInit(init, arrayType, Context);
}
+bool Sema::IsStringInit(Expr *Init, const ArrayType *AT) {
+ return ::IsStringInit(Init, AT, Context) == SIF_None;
+}
+
/// Update the type of a string literal, including any surrounding parentheses,
/// to match the type of the object which it is initializing.
static void updateStringLiteralType(Expr *E, QualType Ty) {
@@ -962,6 +966,8 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
FillInEmptyInitializations(Entity, FullyStructuredList,
RequiresSecondPass, nullptr, 0);
}
+ if (hadError && FullyStructuredList)
+ FullyStructuredList->markError();
}
int InitListChecker::numArrayElements(QualType DeclType) {
@@ -1117,6 +1123,7 @@ static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity,
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_Parameter:
case InitializedEntity::EK_Parameter_CF_Audited:
+ case InitializedEntity::EK_TemplateParameter:
case InitializedEntity::EK_Result:
// Extra braces here are suspicious.
DiagID = diag::warn_braces_around_init;
@@ -1583,10 +1590,7 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
IList->setInit(Index, ResultExpr);
}
}
- if (hadError)
- ++StructuredIndex;
- else
- UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr);
+ UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr);
++Index;
}
@@ -1641,10 +1645,7 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
if (!VerifyOnly && expr)
IList->setInit(Index, expr);
- if (hadError)
- ++StructuredIndex;
- else
- UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
+ UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
++Index;
}
@@ -1695,11 +1696,7 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
IList->setInit(Index, ResultExpr);
}
}
- if (hadError)
- ++StructuredIndex;
- else
- UpdateStructuredListElement(StructuredList, StructuredIndex,
- ResultExpr);
+ UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr);
++Index;
return;
}
@@ -2898,8 +2895,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
Expr *Init = new (Context) IntegerLiteral(
Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc());
if (CharTy != PromotedCharTy)
- Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast,
- Init, nullptr, VK_RValue);
+ Init =
+ ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast, Init,
+ nullptr, VK_RValue, FPOptionsOverride());
StructuredList->updateInit(Context, i, Init);
}
} else {
@@ -2920,8 +2918,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
Expr *Init = new (Context) IntegerLiteral(
Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc());
if (CharTy != PromotedCharTy)
- Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast,
- Init, nullptr, VK_RValue);
+ Init =
+ ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast, Init,
+ nullptr, VK_RValue, FPOptionsOverride());
StructuredList->updateInit(Context, i, Init);
}
}
@@ -3098,8 +3097,12 @@ void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList,
if (Expr *PrevInit = StructuredList->updateInit(SemaRef.Context,
StructuredIndex, expr)) {
- // This initializer overwrites a previous initializer. Warn.
- diagnoseInitOverride(PrevInit, expr->getSourceRange());
+ // This initializer overwrites a previous initializer.
+ // No need to diagnose when `expr` is nullptr because a more relevant
+ // diagnostic has already been issued and this diagnostic is potentially
+ // noise.
+ if (expr)
+ diagnoseInitOverride(PrevInit, expr->getSourceRange());
}
++StructuredIndex;
@@ -3128,7 +3131,8 @@ CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) {
SourceLocation Loc = Index->getBeginLoc();
// Make sure this is an integer constant expression.
- ExprResult Result = S.VerifyIntegerConstantExpression(Index, &Value);
+ ExprResult Result =
+ S.VerifyIntegerConstantExpression(Index, &Value, Sema::AllowFold);
if (Result.isInvalid())
return Result;
@@ -3280,6 +3284,7 @@ DeclarationName InitializedEntity::getName() const {
case EK_Variable:
case EK_Member:
case EK_Binding:
+ case EK_TemplateParameter:
return Variable.VariableOrMember->getDeclName();
case EK_LambdaCapture:
@@ -3310,6 +3315,7 @@ ValueDecl *InitializedEntity::getDecl() const {
case EK_Variable:
case EK_Member:
case EK_Binding:
+ case EK_TemplateParameter:
return Variable.VariableOrMember;
case EK_Parameter:
@@ -3347,6 +3353,7 @@ bool InitializedEntity::allowsNRVO() const {
case EK_Variable:
case EK_Parameter:
case EK_Parameter_CF_Audited:
+ case EK_TemplateParameter:
case EK_Member:
case EK_Binding:
case EK_New:
@@ -3378,6 +3385,7 @@ unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const {
case EK_Parameter: OS << "Parameter"; break;
case EK_Parameter_CF_Audited: OS << "CF audited function Parameter";
break;
+ case EK_TemplateParameter: OS << "TemplateParameter"; break;
case EK_Result: OS << "Result"; break;
case EK_StmtExprResult: OS << "StmtExprResult"; break;
case EK_Exception: OS << "Exception"; break;
@@ -3434,6 +3442,7 @@ void InitializationSequence::Step::Destroy() {
case SK_QualificationConversionRValue:
case SK_QualificationConversionXValue:
case SK_QualificationConversionLValue:
+ case SK_FunctionReferenceConversion:
case SK_AtomicConversion:
case SK_ListInitialization:
case SK_UnwrapInitList:
@@ -3612,6 +3621,13 @@ void InitializationSequence::AddQualificationConversionStep(QualType Ty,
Steps.push_back(S);
}
+void InitializationSequence::AddFunctionReferenceConversionStep(QualType Ty) {
+ Step S;
+ S.Kind = SK_FunctionReferenceConversion;
+ S.Type = Ty;
+ Steps.push_back(S);
+}
+
void InitializationSequence::AddAtomicConversionStep(QualType Ty) {
Step S;
S.Kind = SK_AtomicConversion;
@@ -4099,11 +4115,13 @@ static void TryConstructorInitialization(Sema &S,
IsListInit);
}
if (Result) {
- Sequence.SetOverloadFailure(IsListInit ?
- InitializationSequence::FK_ListConstructorOverloadFailed :
- InitializationSequence::FK_ConstructorOverloadFailed,
- Result);
- return;
+ Sequence.SetOverloadFailure(
+ IsListInit ? InitializationSequence::FK_ListConstructorOverloadFailed
+ : InitializationSequence::FK_ConstructorOverloadFailed,
+ Result);
+
+ if (Result != OR_Deleted)
+ return;
}
bool HadMultipleCandidates = (CandidateSet.size() > 1);
@@ -4124,31 +4142,45 @@ static void TryConstructorInitialization(Sema &S,
return;
}
- // C++11 [dcl.init]p6:
- // If a program calls for the default initialization of an object
- // of a const-qualified type T, T shall be a class type with a
- // user-provided default constructor.
- // C++ core issue 253 proposal:
- // If the implicit default constructor initializes all subobjects, no
- // initializer should be required.
- // The 253 proposal is for example needed to process libstdc++ headers in 5.x.
CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
- if (Kind.getKind() == InitializationKind::IK_Default &&
- Entity.getType().isConstQualified()) {
- if (!CtorDecl->getParent()->allowConstDefaultInit()) {
- if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity))
- Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+ if (Result != OR_Deleted) {
+ // C++11 [dcl.init]p6:
+ // If a program calls for the default initialization of an object
+ // of a const-qualified type T, T shall be a class type with a
+ // user-provided default constructor.
+ // C++ core issue 253 proposal:
+ // If the implicit default constructor initializes all subobjects, no
+ // initializer should be required.
+ // The 253 proposal is for example needed to process libstdc++ headers
+ // in 5.x.
+ if (Kind.getKind() == InitializationKind::IK_Default &&
+ Entity.getType().isConstQualified()) {
+ if (!CtorDecl->getParent()->allowConstDefaultInit()) {
+ if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity))
+ Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+ return;
+ }
+ }
+
+ // C++11 [over.match.list]p1:
+ // In copy-list-initialization, if an explicit constructor is chosen, the
+ // initializer is ill-formed.
+ if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) {
+ Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor);
return;
}
}
- // C++11 [over.match.list]p1:
- // In copy-list-initialization, if an explicit constructor is chosen, the
- // initializer is ill-formed.
- if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) {
- Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor);
+ // [class.copy.elision]p3:
+ // In some copy-initialization contexts, a two-stage overload resolution
+ // is performed.
+ // If the first overload resolution selects a deleted function, we also
+ // need the initialization sequence to decide whether to perform the second
+ // overload resolution.
+ // For deleted functions in other contexts, there is no need to get the
+ // initialization sequence.
+ if (Result == OR_Deleted && Kind.getKind() != InitializationKind::IK_Copy)
return;
- }
// Add the constructor initialization step. Any cv-qualification conversion is
// subsumed by the initialization.
@@ -4232,7 +4264,7 @@ static void TryReferenceListInitialization(Sema &S,
// bind to that.
if (InitList->getNumInits() == 1) {
Expr *Initializer = InitList->getInit(0);
- QualType cv2T2 = Initializer->getType();
+ QualType cv2T2 = S.getCompletedType(Initializer);
Qualifiers T2Quals;
QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals);
@@ -4645,7 +4677,7 @@ static OverloadingResult TryRefInitWithConversionFunction(
else if (RefConv & Sema::ReferenceConversions::ObjC)
Sequence.AddObjCObjectConversionStep(cv1T1);
else if (RefConv & Sema::ReferenceConversions::Function)
- Sequence.AddQualificationConversionStep(cv1T1, VK);
+ Sequence.AddFunctionReferenceConversionStep(cv1T1);
else if (RefConv & Sema::ReferenceConversions::Qualification) {
if (!S.Context.hasSameType(cv1T4, cv1T1))
Sequence.AddQualificationConversionStep(cv1T1, VK);
@@ -4668,7 +4700,7 @@ static void TryReferenceInitialization(Sema &S,
QualType cv1T1 = DestType->castAs<ReferenceType>()->getPointeeType();
Qualifiers T1Quals;
QualType T1 = S.Context.getUnqualifiedArrayType(cv1T1, T1Quals);
- QualType cv2T2 = Initializer->getType();
+ QualType cv2T2 = S.getCompletedType(Initializer);
Qualifiers T2Quals;
QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals);
@@ -4747,12 +4779,12 @@ static void TryReferenceInitializationCore(Sema &S,
Sequence.AddDerivedToBaseCastStep(cv1T1, VK_LValue);
else
Sequence.AddObjCObjectConversionStep(cv1T1);
- } else if (RefConv & (Sema::ReferenceConversions::Qualification |
- Sema::ReferenceConversions::Function)) {
+ } else if (RefConv & Sema::ReferenceConversions::Qualification) {
// Perform a (possibly multi-level) qualification conversion.
- // FIXME: Should we use a different step kind for function conversions?
Sequence.AddQualificationConversionStep(cv1T1,
Initializer->getValueKind());
+ } else if (RefConv & Sema::ReferenceConversions::Function) {
+ Sequence.AddFunctionReferenceConversionStep(cv1T1);
}
// We only create a temporary here when binding a reference to a
@@ -5242,9 +5274,17 @@ static void TryUserDefinedConversion(Sema &S,
if (OverloadingResult Result
= CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
Sequence.SetOverloadFailure(
- InitializationSequence::FK_UserConversionOverloadFailed,
- Result);
- return;
+ InitializationSequence::FK_UserConversionOverloadFailed, Result);
+
+ // [class.copy.elision]p3:
+ // In some copy-initialization contexts, a two-stage overload resolution
+ // is performed.
+ // If the first overload resolution selects a deleted function, we also
+ // need the initialization sequence to decide whether to perform the second
+ // overload resolution.
+ if (!(Result == OR_Deleted &&
+ Kind.getKind() == InitializationKind::IK_Copy))
+ return;
}
FunctionDecl *Function = Best->Function;
@@ -5548,13 +5588,11 @@ static bool TryOCLZeroOpaqueTypeInitialization(Sema &S,
return false;
}
-InitializationSequence::InitializationSequence(Sema &S,
- const InitializedEntity &Entity,
- const InitializationKind &Kind,
- MultiExprArg Args,
- bool TopLevelOfInitList,
- bool TreatUnavailableAsInvalid)
- : FailedCandidateSet(Kind.getLocation(), OverloadCandidateSet::CSK_Normal) {
+InitializationSequence::InitializationSequence(
+ Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind,
+ MultiExprArg Args, bool TopLevelOfInitList, bool TreatUnavailableAsInvalid)
+ : FailedOverloadResult(OR_Success),
+ FailedCandidateSet(Kind.getLocation(), OverloadCandidateSet::CSK_Normal) {
InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList,
TreatUnavailableAsInvalid);
}
@@ -5998,6 +6036,11 @@ getAssignmentAction(const InitializedEntity &Entity, bool Diagnose = false) {
// FIXME: Can we tell apart casting vs. converting?
return Sema::AA_Casting;
+ case InitializedEntity::EK_TemplateParameter:
+ // This is really initialization, but refer to it as conversion for
+ // consistency with CheckConvertedConstantExpression.
+ return Sema::AA_Converting;
+
case InitializedEntity::EK_Member:
case InitializedEntity::EK_Binding:
case InitializedEntity::EK_ArrayElement:
@@ -6032,6 +6075,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
case InitializedEntity::EK_LambdaCapture:
case InitializedEntity::EK_CompoundLiteralInit:
+ case InitializedEntity::EK_TemplateParameter:
return false;
case InitializedEntity::EK_Parameter:
@@ -6066,6 +6110,7 @@ static bool shouldDestroyEntity(const InitializedEntity &Entity) {
case InitializedEntity::EK_Variable:
case InitializedEntity::EK_Parameter:
case InitializedEntity::EK_Parameter_CF_Audited:
+ case InitializedEntity::EK_TemplateParameter:
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_Exception:
@@ -6099,6 +6144,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity,
case InitializedEntity::EK_Member:
case InitializedEntity::EK_Parameter:
case InitializedEntity::EK_Parameter_CF_Audited:
+ case InitializedEntity::EK_TemplateParameter:
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_New:
case InitializedEntity::EK_Base:
@@ -6342,7 +6388,7 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S,
void InitializationSequence::PrintInitLocationNote(Sema &S,
const InitializedEntity &Entity) {
- if (Entity.isParameterKind() && Entity.getDecl()) {
+ if (Entity.isParamOrTemplateParamKind() && Entity.getDecl()) {
if (Entity.getDecl()->getLocation().isInvalid())
return;
@@ -6608,6 +6654,10 @@ static LifetimeResult getEntityLifetime(
// the call.
return {nullptr, LK_FullExpression};
+ case InitializedEntity::EK_TemplateParameter:
+ // FIXME: This will always be ill-formed; should we eagerly diagnose it here?
+ return {nullptr, LK_FullExpression};
+
case InitializedEntity::EK_Result:
// -- The lifetime of a temporary bound to the returned value in a
// function return statement is not extended; the temporary is
@@ -6690,15 +6740,22 @@ struct IndirectLocalPathEntry {
VarInit,
LValToRVal,
LifetimeBoundCall,
+ TemporaryCopy,
+ LambdaCaptureInit,
GslReferenceInit,
GslPointerInit
} Kind;
Expr *E;
- const Decl *D = nullptr;
+ union {
+ const Decl *D = nullptr;
+ const LambdaCapture *Capture;
+ };
IndirectLocalPathEntry() {}
IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {}
IndirectLocalPathEntry(EntryKind K, Expr *E, const Decl *D)
: Kind(K), E(E), D(D) {}
+ IndirectLocalPathEntry(EntryKind K, Expr *E, const LambdaCapture *Capture)
+ : Kind(K), E(E), Capture(Capture) {}
};
using IndirectLocalPath = llvm::SmallVectorImpl<IndirectLocalPathEntry>;
@@ -6892,6 +6949,26 @@ static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) {
if (ATL.getAttrAs<LifetimeBoundAttr>())
return true;
}
+
+ // Assume that all assignment operators with a "normal" return type return
+ // *this, that is, an lvalue reference that is the same type as the implicit
+ // object parameter (or the LHS for a non-member operator$=).
+ OverloadedOperatorKind OO = FD->getDeclName().getCXXOverloadedOperator();
+ if (OO == OO_Equal || isCompoundAssignmentOperator(OO)) {
+ QualType RetT = FD->getReturnType();
+ if (RetT->isLValueReferenceType()) {
+ ASTContext &Ctx = FD->getASTContext();
+ QualType LHST;
+ auto *MD = dyn_cast<CXXMethodDecl>(FD);
+ if (MD && MD->isCXXInstanceMember())
+ LHST = Ctx.getLValueReferenceType(MD->getThisObjectType());
+ else
+ LHST = MD->getParamDecl(0)->getType();
+ if (Ctx.hasSameType(RetT, LHST))
+ return true;
+ }
+ }
+
return false;
}
@@ -7237,15 +7314,37 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
// The lifetime of an init-capture is that of the closure object constructed
// by a lambda-expression.
if (auto *LE = dyn_cast<LambdaExpr>(Init)) {
+ LambdaExpr::capture_iterator CapI = LE->capture_begin();
for (Expr *E : LE->capture_inits()) {
+ assert(CapI != LE->capture_end());
+ const LambdaCapture &Cap = *CapI++;
if (!E)
continue;
+ if (Cap.capturesVariable())
+ Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit, E, &Cap});
if (E->isGLValue())
visitLocalsRetainedByReferenceBinding(Path, E, RK_ReferenceBinding,
Visit, EnableLifetimeWarnings);
else
visitLocalsRetainedByInitializer(Path, E, Visit, true,
EnableLifetimeWarnings);
+ if (Cap.capturesVariable())
+ Path.pop_back();
+ }
+ }
+
+ // Assume that a copy or move from a temporary references the same objects
+ // that the temporary does.
+ if (auto *CCE = dyn_cast<CXXConstructExpr>(Init)) {
+ if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
+ if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) {
+ Expr *Arg = MTE->getSubExpr();
+ Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
+ CCE->getConstructor()});
+ visitLocalsRetainedByInitializer(Path, Arg, Visit, true,
+ /*EnableLifetimeWarnings*/false);
+ Path.pop_back();
+ }
}
}
@@ -7322,14 +7421,31 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
}
}
+/// Whether a path to an object supports lifetime extension.
+enum PathLifetimeKind {
+ /// Lifetime-extend along this path.
+ Extend,
+ /// We should lifetime-extend, but we don't because (due to technical
+ /// limitations) we can't. This happens for default member initializers,
+ /// which we don't clone for every use, so we don't have a unique
+ /// MaterializeTemporaryExpr to update.
+ ShouldExtend,
+ /// Do not lifetime extend along this path.
+ NoExtend
+};
+
/// Determine whether this is an indirect path to a temporary that we are
-/// supposed to lifetime-extend along (but don't).
-static bool shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) {
+/// supposed to lifetime-extend along.
+static PathLifetimeKind
+shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) {
+ PathLifetimeKind Kind = PathLifetimeKind::Extend;
for (auto Elem : Path) {
- if (Elem.Kind != IndirectLocalPathEntry::DefaultInit)
- return false;
+ if (Elem.Kind == IndirectLocalPathEntry::DefaultInit)
+ Kind = PathLifetimeKind::ShouldExtend;
+ else if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit)
+ return PathLifetimeKind::NoExtend;
}
- return true;
+ return Kind;
}
/// Find the range for the first interesting entry in the path at or after I.
@@ -7340,6 +7456,7 @@ static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
case IndirectLocalPathEntry::AddressOf:
case IndirectLocalPathEntry::LValToRVal:
case IndirectLocalPathEntry::LifetimeBoundCall:
+ case IndirectLocalPathEntry::TemporaryCopy:
case IndirectLocalPathEntry::GslReferenceInit:
case IndirectLocalPathEntry::GslPointerInit:
// These exist primarily to mark the path as not permitting or
@@ -7352,6 +7469,11 @@ static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
LLVM_FALLTHROUGH;
case IndirectLocalPathEntry::DefaultInit:
return Path[I].E->getSourceRange();
+
+ case IndirectLocalPathEntry::LambdaCaptureInit:
+ if (!Path[I].Capture->capturesVariable())
+ continue;
+ return Path[I].E->getSourceRange();
}
}
return E->getSourceRange();
@@ -7429,17 +7551,16 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
return false;
}
- // Lifetime-extend the temporary.
- if (Path.empty()) {
+ switch (shouldLifetimeExtendThroughPath(Path)) {
+ case PathLifetimeKind::Extend:
// Update the storage duration of the materialized temporary.
// FIXME: Rebuild the expression instead of mutating it.
MTE->setExtendingDecl(ExtendingEntity->getDecl(),
ExtendingEntity->allocateManglingNumber());
// Also visit the temporaries lifetime-extended by this initializer.
return true;
- }
- if (shouldLifetimeExtendThroughPath(Path)) {
+ case PathLifetimeKind::ShouldExtend:
// We're supposed to lifetime-extend the temporary along this path (per
// the resolution of DR1815), but we don't support that yet.
//
@@ -7448,7 +7569,9 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
// lifetime extend its temporaries.
Diag(DiagLoc, diag::warn_unsupported_lifetime_extension)
<< RK << DiagRange;
- } else {
+ break;
+
+ case PathLifetimeKind::NoExtend:
// If the path goes through the initialization of a variable or field,
// it can't possibly reach a temporary created in this full-expression.
// We will have already diagnosed any problems with the initializer.
@@ -7459,6 +7582,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
<< RK << !Entity.getParent()
<< ExtendingEntity->getDecl()->isImplicit()
<< ExtendingEntity->getDecl() << Init->isGLValue() << DiagRange;
+ break;
}
break;
}
@@ -7479,7 +7603,8 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
return false;
}
bool IsSubobjectMember = ExtendingEntity != &Entity;
- Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path)
+ Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path) !=
+ PathLifetimeKind::NoExtend
? diag::err_dangling_member
: diag::warn_dangling_member)
<< ExtendingDecl << IsSubobjectMember << RK << DiagRange;
@@ -7586,6 +7711,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
break;
case IndirectLocalPathEntry::LifetimeBoundCall:
+ case IndirectLocalPathEntry::TemporaryCopy:
case IndirectLocalPathEntry::GslPointerInit:
case IndirectLocalPathEntry::GslReferenceInit:
// FIXME: Consider adding a note for these.
@@ -7598,7 +7724,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
break;
}
- case IndirectLocalPathEntry::VarInit:
+ case IndirectLocalPathEntry::VarInit: {
const VarDecl *VD = cast<VarDecl>(Elem.D);
Diag(VD->getLocation(), diag::note_local_var_initializer)
<< VD->getType()->isReferenceType()
@@ -7606,6 +7732,19 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
<< nextPathEntryRange(Path, I + 1, L);
break;
}
+
+ case IndirectLocalPathEntry::LambdaCaptureInit:
+ if (!Elem.Capture->capturesVariable())
+ break;
+ // FIXME: We can't easily tell apart an init-capture from a nested
+ // capture of an init-capture.
+ const VarDecl *VD = Elem.Capture->getCapturedVar();
+ Diag(Elem.Capture->getLocation(), diag::note_lambda_capture_initializer)
+ << VD << VD->isInitCapture() << Elem.Capture->isExplicit()
+ << (Elem.Capture->getCaptureKind() == LCK_ByRef) << VD
+ << nextPathEntryRange(Path, I + 1, L);
+ break;
+ }
}
// We didn't lifetime-extend, so don't go any further; we don't need more
@@ -7879,7 +8018,7 @@ ExprResult InitializationSequence::Perform(Sema &S,
if (S.getLangOpts().CPlusPlus11 && Entity.getType()->isReferenceType() &&
Args.size() == 1 && isa<InitListExpr>(Args[0]) &&
- !Entity.isParameterKind()) {
+ !Entity.isParamOrTemplateParamKind()) {
// Produce a C++98 compatibility warning if we are initializing a reference
// from an initializer list. For parameters, we produce a better warning
// elsewhere.
@@ -7929,6 +8068,7 @@ ExprResult InitializationSequence::Perform(Sema &S,
case SK_QualificationConversionLValue:
case SK_QualificationConversionXValue:
case SK_QualificationConversionRValue:
+ case SK_FunctionReferenceConversion:
case SK_AtomicConversion:
case SK_ConversionSequence:
case SK_ConversionSequenceNoNarrowing:
@@ -8023,9 +8163,9 @@ ExprResult InitializationSequence::Perform(Sema &S,
(Step->Kind == SK_CastDerivedToBaseXValue ?
VK_XValue :
VK_RValue);
- CurInit =
- ImplicitCastExpr::Create(S.Context, Step->Type, CK_DerivedToBase,
- CurInit.get(), &BasePath, VK);
+ CurInit = ImplicitCastExpr::Create(S.Context, Step->Type,
+ CK_DerivedToBase, CurInit.get(),
+ &BasePath, VK, FPOptionsOverride());
break;
}
@@ -8060,9 +8200,21 @@ ExprResult InitializationSequence::Perform(Sema &S,
if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
return ExprError();
+ QualType MTETy = Step->Type;
+
+ // When this is an incomplete array type (such as when this is
+ // initializing an array of unknown bounds from an init list), use THAT
+ // type instead so that we propogate the array bounds.
+ if (MTETy->isIncompleteArrayType() &&
+ !CurInit.get()->getType()->isIncompleteArrayType() &&
+ S.Context.hasSameType(
+ MTETy->getPointeeOrArrayElementType(),
+ CurInit.get()->getType()->getPointeeOrArrayElementType()))
+ MTETy = CurInit.get()->getType();
+
// Materialize the temporary into memory.
MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr(
- Step->Type, CurInit.get(), Entity.getType()->isLValueReferenceType());
+ MTETy, CurInit.get(), Entity.getType()->isLValueReferenceType());
CurInit = MTE;
// If we're extending this temporary to automatic storage duration -- we
@@ -8154,9 +8306,9 @@ ExprResult InitializationSequence::Perform(Sema &S,
if (CreatedObject && checkAbstractType(CurInit.get()->getType()))
return ExprError();
- CurInit = ImplicitCastExpr::Create(S.Context, CurInit.get()->getType(),
- CastKind, CurInit.get(), nullptr,
- CurInit.get()->getValueKind());
+ CurInit = ImplicitCastExpr::Create(
+ S.Context, CurInit.get()->getType(), CastKind, CurInit.get(), nullptr,
+ CurInit.get()->getValueKind(), S.CurFPFeatureOverrides());
if (shouldBindAsTemporary(Entity))
// The overall entity is temporary, so this expression should be
@@ -8194,6 +8346,13 @@ ExprResult InitializationSequence::Perform(Sema &S,
break;
}
+ case SK_FunctionReferenceConversion:
+ assert(CurInit.get()->isLValue() &&
+ "function reference should be lvalue");
+ CurInit =
+ S.ImpCastExprToType(CurInit.get(), Step->Type, CK_NoOp, VK_LValue);
+ break;
+
case SK_AtomicConversion: {
assert(CurInit.get()->isRValue() && "cannot convert glvalue to atomic");
CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type,
@@ -8422,7 +8581,8 @@ ExprResult InitializationSequence::Perform(Sema &S,
case SK_StringInit: {
QualType Ty = Step->Type;
- CheckStringInit(CurInit.get(), ResultType ? *ResultType : Ty,
+ bool UpdateType = ResultType && Entity.getType()->isIncompleteArrayType();
+ CheckStringInit(CurInit.get(), UpdateType ? *ResultType : Ty,
S.Context.getAsArrayType(Ty), S);
break;
}
@@ -8497,9 +8657,9 @@ ExprResult InitializationSequence::Perform(Sema &S,
break;
case SK_ProduceObjCObject:
- CurInit =
- ImplicitCastExpr::Create(S.Context, Step->Type, CK_ARCProduceObject,
- CurInit.get(), nullptr, VK_RValue);
+ CurInit = ImplicitCastExpr::Create(
+ S.Context, Step->Type, CK_ARCProduceObject, CurInit.get(), nullptr,
+ VK_RValue, FPOptionsOverride());
break;
case SK_StdInitializerList: {
@@ -8553,9 +8713,9 @@ ExprResult InitializationSequence::Perform(Sema &S,
// Case 1b and 1c
// No cast from integer to sampler is needed.
if (!Var->hasGlobalStorage()) {
- CurInit = ImplicitCastExpr::Create(S.Context, Step->Type,
- CK_LValueToRValue, Init,
- /*BasePath=*/nullptr, VK_RValue);
+ CurInit = ImplicitCastExpr::Create(
+ S.Context, Step->Type, CK_LValueToRValue, Init,
+ /*BasePath=*/nullptr, VK_RValue, FPOptionsOverride());
break;
}
// Case 1a
@@ -8705,6 +8865,16 @@ static void emitBadConversionNotes(Sema &S, const InitializedEntity &entity,
if (entity.getKind() == InitializedEntity::EK_Result)
S.EmitRelatedResultTypeNoteForReturn(destType);
}
+ QualType fromType = op->getType();
+ auto *fromDecl = fromType.getTypePtr()->getPointeeCXXRecordDecl();
+ auto *destDecl = destType.getTypePtr()->getPointeeCXXRecordDecl();
+ if (fromDecl && destDecl && fromDecl->getDeclKind() == Decl::CXXRecord &&
+ destDecl->getDeclKind() == Decl::CXXRecord &&
+ !fromDecl->isInvalidDecl() && !destDecl->isInvalidDecl() &&
+ !fromDecl->hasDefinition())
+ S.Diag(fromDecl->getLocation(), diag::note_forward_class_conversion)
+ << S.getASTContext().getTagDeclType(fromDecl)
+ << S.getASTContext().getTagDeclType(destDecl);
}
static void diagnoseListInit(Sema &S, const InitializedEntity &Entity,
@@ -9443,6 +9613,10 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "qualification conversion (lvalue)";
break;
+ case SK_FunctionReferenceConversion:
+ OS << "function reference conversion";
+ break;
+
case SK_AtomicConversion:
OS << "non-atomic-to-atomic conversion";
break;
@@ -9747,7 +9921,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
auto TemplateName = DeducedTST->getTemplateName();
if (TemplateName.isDependent())
- return Context.DependentTy;
+ return SubstAutoType(TSInfo->getType(), Context.DependentTy);
// We can only perform deduction for class templates.
auto *Template =
@@ -9766,7 +9940,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
Diag(TSInfo->getTypeLoc().getBeginLoc(),
diag::warn_cxx14_compat_class_template_argument_deduction)
<< TSInfo->getTypeLoc().getSourceRange() << 0;
- return Context.DependentTy;
+ return SubstAutoType(TSInfo->getType(), Context.DependentTy);
}
// FIXME: Perform "exact type" matching first, per CWG discussion?
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 657ed13f207a..af61c82c2002 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -233,7 +233,7 @@ getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) {
/*L angle loc*/ LSI->ExplicitTemplateParamsRange.getBegin(),
LSI->TemplateParams,
/*R angle loc*/LSI->ExplicitTemplateParamsRange.getEnd(),
- nullptr);
+ LSI->RequiresClause.get());
}
return LSI->GLTemplateParameterList;
}
@@ -520,7 +520,8 @@ void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {
void Sema::ActOnLambdaExplicitTemplateParameterList(SourceLocation LAngleLoc,
ArrayRef<NamedDecl *> TParams,
- SourceLocation RAngleLoc) {
+ SourceLocation RAngleLoc,
+ ExprResult RequiresClause) {
LambdaScopeInfo *LSI = getCurLambda();
assert(LSI && "Expected a lambda scope");
assert(LSI->NumExplicitTemplateParams == 0 &&
@@ -533,6 +534,7 @@ void Sema::ActOnLambdaExplicitTemplateParameterList(SourceLocation LAngleLoc,
LSI->TemplateParams.append(TParams.begin(), TParams.end());
LSI->NumExplicitTemplateParams = TParams.size();
LSI->ExplicitTemplateParamsRange = {LAngleLoc, RAngleLoc};
+ LSI->RequiresClause = RequiresClause;
}
void Sema::addLambdaParameters(
@@ -680,8 +682,9 @@ static void adjustBlockReturnsToEnum(Sema &S, ArrayRef<ReturnStmt*> returns,
ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(retValue);
Expr *E = (cleanups ? cleanups->getSubExpr() : retValue);
- E = ImplicitCastExpr::Create(S.Context, returnType, CK_IntegralCast,
- E, /*base path*/ nullptr, VK_RValue);
+ E = ImplicitCastExpr::Create(S.Context, returnType, CK_IntegralCast, E,
+ /*base path*/ nullptr, VK_RValue,
+ FPOptionsOverride());
if (cleanups) {
cleanups->setSubExpr(E);
} else {
@@ -803,7 +806,8 @@ QualType Sema::buildLambdaInitCaptureInitialization(
Diag(EllipsisLoc, getLangOpts().CPlusPlus20
? diag::warn_cxx17_compat_init_capture_pack
: diag::ext_init_capture_pack);
- DeductType = Context.getPackExpansionType(DeductType, NumExpansions);
+ DeductType = Context.getPackExpansionType(DeductType, NumExpansions,
+ /*ExpectPackInType=*/false);
TLB.push<PackExpansionTypeLoc>(DeductType).setEllipsisLoc(EllipsisLoc);
} else {
// Just ignore the ellipsis for now and form a non-pack variable. We'll
@@ -994,6 +998,10 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
if (getLangOpts().CUDA)
CUDASetLambdaAttrs(Method);
+ // OpenMP lambdas might get assumumption attributes.
+ if (LangOpts.OpenMP)
+ ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Method);
+
// Number the lambda for linkage purposes if necessary.
handleLambdaNumbering(Class, Method);
@@ -1261,30 +1269,89 @@ void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
PopFunctionScopeInfo();
}
+template <typename Func>
+static void repeatForLambdaConversionFunctionCallingConvs(
+ Sema &S, const FunctionProtoType &CallOpProto, Func F) {
+ CallingConv DefaultFree = S.Context.getDefaultCallingConvention(
+ CallOpProto.isVariadic(), /*IsCXXMethod=*/false);
+ CallingConv DefaultMember = S.Context.getDefaultCallingConvention(
+ CallOpProto.isVariadic(), /*IsCXXMethod=*/true);
+ CallingConv CallOpCC = CallOpProto.getCallConv();
+
+ /// Implement emitting a version of the operator for many of the calling
+ /// conventions for MSVC, as described here:
+ /// https://devblogs.microsoft.com/oldnewthing/20150220-00/?p=44623.
+ /// Experimentally, we determined that cdecl, stdcall, fastcall, and
+ /// vectorcall are generated by MSVC when it is supported by the target.
+ /// Additionally, we are ensuring that the default-free/default-member and
+ /// call-operator calling convention are generated as well.
+ /// NOTE: We intentionally generate a 'thiscall' on Win32 implicitly from the
+ /// 'member default', despite MSVC not doing so. We do this in order to ensure
+ /// that someone who intentionally places 'thiscall' on the lambda call
+ /// operator will still get that overload, since we don't have the a way of
+ /// detecting the attribute by the time we get here.
+ if (S.getLangOpts().MSVCCompat) {
+ CallingConv Convs[] = {
+ CC_C, CC_X86StdCall, CC_X86FastCall, CC_X86VectorCall,
+ DefaultFree, DefaultMember, CallOpCC};
+ llvm::sort(Convs);
+ llvm::iterator_range<CallingConv *> Range(
+ std::begin(Convs), std::unique(std::begin(Convs), std::end(Convs)));
+ const TargetInfo &TI = S.getASTContext().getTargetInfo();
+
+ for (CallingConv C : Range) {
+ if (TI.checkCallingConvention(C) == TargetInfo::CCCR_OK)
+ F(C);
+ }
+ return;
+ }
+
+ if (CallOpCC == DefaultMember && DefaultMember != DefaultFree) {
+ F(DefaultFree);
+ F(DefaultMember);
+ } else {
+ F(CallOpCC);
+ }
+}
+
+// Returns the 'standard' calling convention to be used for the lambda
+// conversion function, that is, the 'free' function calling convention unless
+// it is overridden by a non-default calling convention attribute.
+static CallingConv
+getLambdaConversionFunctionCallConv(Sema &S,
+ const FunctionProtoType *CallOpProto) {
+ CallingConv DefaultFree = S.Context.getDefaultCallingConvention(
+ CallOpProto->isVariadic(), /*IsCXXMethod=*/false);
+ CallingConv DefaultMember = S.Context.getDefaultCallingConvention(
+ CallOpProto->isVariadic(), /*IsCXXMethod=*/true);
+ CallingConv CallOpCC = CallOpProto->getCallConv();
+
+ // If the call-operator hasn't been changed, return both the 'free' and
+ // 'member' function calling convention.
+ if (CallOpCC == DefaultMember && DefaultMember != DefaultFree)
+ return DefaultFree;
+ return CallOpCC;
+}
+
QualType Sema::getLambdaConversionFunctionResultType(
- const FunctionProtoType *CallOpProto) {
- // The function type inside the pointer type is the same as the call
- // operator with some tweaks. The calling convention is the default free
- // function convention, and the type qualifications are lost.
+ const FunctionProtoType *CallOpProto, CallingConv CC) {
const FunctionProtoType::ExtProtoInfo CallOpExtInfo =
CallOpProto->getExtProtoInfo();
FunctionProtoType::ExtProtoInfo InvokerExtInfo = CallOpExtInfo;
- CallingConv CC = Context.getDefaultCallingConvention(
- CallOpProto->isVariadic(), /*IsCXXMethod=*/false);
InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC);
InvokerExtInfo.TypeQuals = Qualifiers();
assert(InvokerExtInfo.RefQualifier == RQ_None &&
- "Lambda's call operator should not have a reference qualifier");
+ "Lambda's call operator should not have a reference qualifier");
return Context.getFunctionType(CallOpProto->getReturnType(),
CallOpProto->getParamTypes(), InvokerExtInfo);
}
/// Add a lambda's conversion to function pointer, as described in
/// C++11 [expr.prim.lambda]p6.
-static void addFunctionPointerConversion(Sema &S,
- SourceRange IntroducerRange,
+static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange,
CXXRecordDecl *Class,
- CXXMethodDecl *CallOperator) {
+ CXXMethodDecl *CallOperator,
+ QualType InvokerFunctionTy) {
// This conversion is explicitly disabled if the lambda's function has
// pass_object_size attributes on any of its parameters.
auto HasPassObjectSizeAttr = [](const ParmVarDecl *P) {
@@ -1294,8 +1361,6 @@ static void addFunctionPointerConversion(Sema &S,
return;
// Add the conversion to function pointer.
- QualType InvokerFunctionTy = S.getLambdaConversionFunctionResultType(
- CallOperator->getType()->castAs<FunctionProtoType>());
QualType PtrToFunctionTy = S.Context.getPointerType(InvokerFunctionTy);
// Create the type of the conversion function.
@@ -1380,7 +1445,8 @@ static void addFunctionPointerConversion(Sema &S,
S.Context, Class, Loc,
DeclarationNameInfo(ConversionName, Loc, ConvNameLoc), ConvTy, ConvTSI,
/*isInline=*/true, ExplicitSpecifier(),
- S.getLangOpts().CPlusPlus17 ? CSK_constexpr : CSK_unspecified,
+ S.getLangOpts().CPlusPlus17 ? ConstexprSpecKind::Constexpr
+ : ConstexprSpecKind::Unspecified,
CallOperator->getBody()->getEndLoc());
Conversion->setAccess(AS_public);
Conversion->setImplicit(true);
@@ -1419,7 +1485,8 @@ static void addFunctionPointerConversion(Sema &S,
CXXMethodDecl *Invoke = CXXMethodDecl::Create(
S.Context, Class, Loc, DeclarationNameInfo(InvokerName, Loc),
InvokerFunctionTy, CallOperator->getTypeSourceInfo(), SC_Static,
- /*isInline=*/true, CSK_unspecified, CallOperator->getBody()->getEndLoc());
+ /*isInline=*/true, ConstexprSpecKind::Unspecified,
+ CallOperator->getBody()->getEndLoc());
for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I)
InvokerParams[I]->setOwningFunction(Invoke);
Invoke->setParams(InvokerParams);
@@ -1440,13 +1507,34 @@ static void addFunctionPointerConversion(Sema &S,
Class->addDecl(Invoke);
}
+/// Add a lambda's conversion to function pointers, as described in
+/// C++11 [expr.prim.lambda]p6. Note that in most cases, this should emit only a
+/// single pointer conversion. In the event that the default calling convention
+/// for free and member functions is different, it will emit both conventions.
+static void addFunctionPointerConversions(Sema &S, SourceRange IntroducerRange,
+ CXXRecordDecl *Class,
+ CXXMethodDecl *CallOperator) {
+ const FunctionProtoType *CallOpProto =
+ CallOperator->getType()->castAs<FunctionProtoType>();
+
+ repeatForLambdaConversionFunctionCallingConvs(
+ S, *CallOpProto, [&](CallingConv CC) {
+ QualType InvokerFunctionTy =
+ S.getLambdaConversionFunctionResultType(CallOpProto, CC);
+ addFunctionPointerConversion(S, IntroducerRange, Class, CallOperator,
+ InvokerFunctionTy);
+ });
+}
+
/// Add a lambda's conversion to block pointer.
static void addBlockPointerConversion(Sema &S,
SourceRange IntroducerRange,
CXXRecordDecl *Class,
CXXMethodDecl *CallOperator) {
+ const FunctionProtoType *CallOpProto =
+ CallOperator->getType()->castAs<FunctionProtoType>();
QualType FunctionTy = S.getLambdaConversionFunctionResultType(
- CallOperator->getType()->castAs<FunctionProtoType>());
+ CallOpProto, getLambdaConversionFunctionCallConv(S, CallOpProto));
QualType BlockPtrTy = S.Context.getBlockPointerType(FunctionTy);
FunctionProtoType::ExtProtoInfo ConversionEPI(
@@ -1465,7 +1553,7 @@ static void addBlockPointerConversion(Sema &S,
CXXConversionDecl *Conversion = CXXConversionDecl::Create(
S.Context, Class, Loc, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy,
S.Context.getTrivialTypeSourceInfo(ConvTy, Loc),
- /*isInline=*/true, ExplicitSpecifier(), CSK_unspecified,
+ /*isInline=*/true, ExplicitSpecifier(), ConstexprSpecKind::Unspecified,
CallOperator->getBody()->getEndLoc());
Conversion->setAccess(AS_public);
Conversion->setImplicit(true);
@@ -1623,8 +1711,9 @@ FieldDecl *Sema::BuildCaptureField(RecordDecl *RD,
// Build the non-static data member.
FieldDecl *Field =
- FieldDecl::Create(Context, RD, Loc, Loc, nullptr, FieldType, TSI, nullptr,
- false, ICIS_NoInit);
+ FieldDecl::Create(Context, RD, /*StartLoc=*/Loc, /*IdLoc=*/Loc,
+ /*Id=*/nullptr, FieldType, TSI, /*BW=*/nullptr,
+ /*Mutable=*/false, ICIS_NoInit);
// If the variable being captured has an invalid type, mark the class as
// invalid as well.
if (!FieldType->isDependentType()) {
@@ -1784,7 +1873,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
CUDACheckLambdaCapture(CallOperator, From);
}
- Class->setCaptures(Captures);
+ Class->setCaptures(Context, Captures);
// C++11 [expr.prim.lambda]p6:
// The closure type for a lambda-expression with no lambda-capture
@@ -1792,8 +1881,8 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
// to pointer to function having the same parameter and return
// types as the closure type's function call operator.
if (Captures.empty() && CaptureDefault == LCD_None)
- addFunctionPointerConversion(*this, IntroducerRange, Class,
- CallOperator);
+ addFunctionPointerConversions(*this, IntroducerRange, Class,
+ CallOperator);
// Objective-C++:
// The closure type for a lambda-expression has a public non-virtual
@@ -1828,8 +1917,8 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
CallOperator->setConstexprKind(
CheckConstexprFunctionDefinition(CallOperator,
CheckConstexprKind::CheckValid)
- ? CSK_constexpr
- : CSK_unspecified);
+ ? ConstexprSpecKind::Constexpr
+ : ConstexprSpecKind::Unspecified);
}
// Emit delayed shadowing warnings now that the full capture list is known.
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 5757eaf3fac0..29038ab9fe1c 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -894,10 +894,9 @@ bool Sema::LookupBuiltin(LookupResult &R) {
Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
return false;
- if (NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II,
- BuiltinID, TUScope,
- R.isForRedeclaration(),
- R.getNameLoc())) {
+ if (NamedDecl *D =
+ LazilyCreateBuiltin(II, BuiltinID, TUScope,
+ R.isForRedeclaration(), R.getNameLoc())) {
R.addDecl(D);
return true;
}
@@ -908,6 +907,24 @@ bool Sema::LookupBuiltin(LookupResult &R) {
return false;
}
+/// Looks up the declaration of "struct objc_super" and
+/// saves it for later use in building builtin declaration of
+/// objc_msgSendSuper and objc_msgSendSuper_stret.
+static void LookupPredefedObjCSuperType(Sema &Sema, Scope *S) {
+ ASTContext &Context = Sema.Context;
+ LookupResult Result(Sema, &Context.Idents.get("objc_super"), SourceLocation(),
+ Sema::LookupTagName);
+ Sema.LookupName(Result, S);
+ if (Result.getResultKind() == LookupResult::Found)
+ if (const TagDecl *TD = Result.getAsSingle<TagDecl>())
+ Context.setObjCSuperType(Context.getTagDeclType(TD));
+}
+
+void Sema::LookupNecessaryTypesForBuiltin(Scope *S, unsigned ID) {
+ if (ID == Builtin::BIobjc_msgSendSuper)
+ LookupPredefedObjCSuperType(*this, S);
+}
+
/// Determine whether we can declare a special member function within
/// the class at this point.
static bool CanDeclareSpecialMemberFunction(const CXXRecordDecl *Class) {
@@ -2068,47 +2085,6 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
return Found;
}
-/// Callback that looks for any member of a class with the given name.
-static bool LookupAnyMember(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path, DeclarationName Name) {
- RecordDecl *BaseRecord = Specifier->getType()->castAs<RecordType>()->getDecl();
-
- Path.Decls = BaseRecord->lookup(Name);
- return !Path.Decls.empty();
-}
-
-/// Determine whether the given set of member declarations contains only
-/// static members, nested types, and enumerators.
-template<typename InputIterator>
-static bool HasOnlyStaticMembers(InputIterator First, InputIterator Last) {
- Decl *D = (*First)->getUnderlyingDecl();
- if (isa<VarDecl>(D) || isa<TypeDecl>(D) || isa<EnumConstantDecl>(D))
- return true;
-
- if (isa<CXXMethodDecl>(D)) {
- // Determine whether all of the methods are static.
- bool AllMethodsAreStatic = true;
- for(; First != Last; ++First) {
- D = (*First)->getUnderlyingDecl();
-
- if (!isa<CXXMethodDecl>(D)) {
- assert(isa<TagDecl>(D) && "Non-function must be a tag decl");
- break;
- }
-
- if (!cast<CXXMethodDecl>(D)->isStatic()) {
- AllMethodsAreStatic = false;
- break;
- }
- }
-
- if (AllMethodsAreStatic)
- return true;
- }
-
- return false;
-}
-
/// Perform qualified name lookup into a given context.
///
/// Qualified name lookup (C++ [basic.lookup.qual]) is used to find
@@ -2186,6 +2162,13 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
if (!LookupRec || !LookupRec->getDefinition())
return false;
+ // We're done for lookups that can never succeed for C++ classes.
+ if (R.getLookupKind() == LookupOperatorName ||
+ R.getLookupKind() == LookupNamespaceName ||
+ R.getLookupKind() == LookupObjCProtocolName ||
+ R.getLookupKind() == LookupLabel)
+ return false;
+
// If we're performing qualified name lookup into a dependent class,
// then we are actually looking into a current instantiation. If we have any
// dependent base classes, then we either have to delay lookup until
@@ -2198,59 +2181,27 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
}
// Perform lookup into our base classes.
- CXXBasePaths Paths;
- Paths.setOrigin(LookupRec);
-
- // Look for this member in our base classes
- bool (*BaseCallback)(const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
- DeclarationName Name) = nullptr;
- switch (R.getLookupKind()) {
- case LookupObjCImplicitSelfParam:
- case LookupOrdinaryName:
- case LookupMemberName:
- case LookupRedeclarationWithLinkage:
- case LookupLocalFriendName:
- case LookupDestructorName:
- BaseCallback = &CXXRecordDecl::FindOrdinaryMember;
- break;
-
- case LookupTagName:
- BaseCallback = &CXXRecordDecl::FindTagMember;
- break;
-
- case LookupAnyName:
- BaseCallback = &LookupAnyMember;
- break;
-
- case LookupOMPReductionName:
- BaseCallback = &CXXRecordDecl::FindOMPReductionMember;
- break;
-
- case LookupOMPMapperName:
- BaseCallback = &CXXRecordDecl::FindOMPMapperMember;
- break;
-
- case LookupUsingDeclName:
- // This lookup is for redeclarations only.
-
- case LookupOperatorName:
- case LookupNamespaceName:
- case LookupObjCProtocolName:
- case LookupLabel:
- // These lookups will never find a member in a C++ class (or base class).
- return false;
-
- case LookupNestedNameSpecifierName:
- BaseCallback = &CXXRecordDecl::FindNestedNameSpecifierMember;
- break;
- }
DeclarationName Name = R.getLookupName();
- if (!LookupRec->lookupInBases(
- [=](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
- return BaseCallback(Specifier, Path, Name);
- },
- Paths))
+ unsigned IDNS = R.getIdentifierNamespace();
+
+ // Look for this member in our base classes.
+ auto BaseCallback = [Name, IDNS](const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path) -> bool {
+ CXXRecordDecl *BaseRecord = Specifier->getType()->getAsCXXRecordDecl();
+ // Drop leading non-matching lookup results from the declaration list so
+ // we don't need to consider them again below.
+ for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty();
+ Path.Decls = Path.Decls.slice(1)) {
+ if (Path.Decls.front()->isInIdentifierNamespace(IDNS))
+ return true;
+ }
+ return false;
+ };
+
+ CXXBasePaths Paths;
+ Paths.setOrigin(LookupRec);
+ if (!LookupRec->lookupInBases(BaseCallback, Paths))
return false;
R.setNamingClass(LookupRec);
@@ -2265,6 +2216,85 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
int SubobjectNumber = 0;
AccessSpecifier SubobjectAccess = AS_none;
+ // Check whether the given lookup result contains only static members.
+ auto HasOnlyStaticMembers = [&](DeclContextLookupResult Result) {
+ for (NamedDecl *ND : Result)
+ if (ND->isInIdentifierNamespace(IDNS) && ND->isCXXInstanceMember())
+ return false;
+ return true;
+ };
+
+ bool TemplateNameLookup = R.isTemplateNameLookup();
+
+ // Determine whether two sets of members contain the same members, as
+ // required by C++ [class.member.lookup]p6.
+ auto HasSameDeclarations = [&](DeclContextLookupResult A,
+ DeclContextLookupResult B) {
+ using Iterator = DeclContextLookupResult::iterator;
+ using Result = const void *;
+
+ auto Next = [&](Iterator &It, Iterator End) -> Result {
+ while (It != End) {
+ NamedDecl *ND = *It++;
+ if (!ND->isInIdentifierNamespace(IDNS))
+ continue;
+
+ // C++ [temp.local]p3:
+ // A lookup that finds an injected-class-name (10.2) can result in
+ // an ambiguity in certain cases (for example, if it is found in
+ // more than one base class). If all of the injected-class-names
+ // that are found refer to specializations of the same class
+ // template, and if the name is used as a template-name, the
+ // reference refers to the class template itself and not a
+ // specialization thereof, and is not ambiguous.
+ if (TemplateNameLookup)
+ if (auto *TD = getAsTemplateNameDecl(ND))
+ ND = TD;
+
+ // C++ [class.member.lookup]p3:
+ // type declarations (including injected-class-names) are replaced by
+ // the types they designate
+ if (const TypeDecl *TD = dyn_cast<TypeDecl>(ND->getUnderlyingDecl())) {
+ QualType T = Context.getTypeDeclType(TD);
+ return T.getCanonicalType().getAsOpaquePtr();
+ }
+
+ return ND->getUnderlyingDecl()->getCanonicalDecl();
+ }
+ return nullptr;
+ };
+
+ // We'll often find the declarations are in the same order. Handle this
+ // case (and the special case of only one declaration) efficiently.
+ Iterator AIt = A.begin(), BIt = B.begin(), AEnd = A.end(), BEnd = B.end();
+ while (true) {
+ Result AResult = Next(AIt, AEnd);
+ Result BResult = Next(BIt, BEnd);
+ if (!AResult && !BResult)
+ return true;
+ if (!AResult || !BResult)
+ return false;
+ if (AResult != BResult) {
+ // Found a mismatch; carefully check both lists, accounting for the
+ // possibility of declarations appearing more than once.
+ llvm::SmallDenseMap<Result, bool, 32> AResults;
+ for (; AResult; AResult = Next(AIt, AEnd))
+ AResults.insert({AResult, /*FoundInB*/false});
+ unsigned Found = 0;
+ for (; BResult; BResult = Next(BIt, BEnd)) {
+ auto It = AResults.find(BResult);
+ if (It == AResults.end())
+ return false;
+ if (!It->second) {
+ It->second = true;
+ ++Found;
+ }
+ }
+ return AResults.size() == Found;
+ }
+ }
+ };
+
for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathEnd = Paths.end();
Path != PathEnd; ++Path) {
const CXXBasePathElement &PathElement = Path->back();
@@ -2281,51 +2311,25 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
continue;
}
- if (SubobjectType
- != Context.getCanonicalType(PathElement.Base->getType())) {
+ if (SubobjectType !=
+ Context.getCanonicalType(PathElement.Base->getType())) {
// We found members of the given name in two subobjects of
// different types. If the declaration sets aren't the same, this
// lookup is ambiguous.
- if (HasOnlyStaticMembers(Path->Decls.begin(), Path->Decls.end())) {
- CXXBasePaths::paths_iterator FirstPath = Paths.begin();
- DeclContext::lookup_iterator FirstD = FirstPath->Decls.begin();
- DeclContext::lookup_iterator CurrentD = Path->Decls.begin();
-
- // Get the decl that we should use for deduplicating this lookup.
- auto GetRepresentativeDecl = [&](NamedDecl *D) -> Decl * {
- // C++ [temp.local]p3:
- // A lookup that finds an injected-class-name (10.2) can result in
- // an ambiguity in certain cases (for example, if it is found in
- // more than one base class). If all of the injected-class-names
- // that are found refer to specializations of the same class
- // template, and if the name is used as a template-name, the
- // reference refers to the class template itself and not a
- // specialization thereof, and is not ambiguous.
- if (R.isTemplateNameLookup())
- if (auto *TD = getAsTemplateNameDecl(D))
- D = TD;
- return D->getUnderlyingDecl()->getCanonicalDecl();
- };
-
- while (FirstD != FirstPath->Decls.end() &&
- CurrentD != Path->Decls.end()) {
- if (GetRepresentativeDecl(*FirstD) !=
- GetRepresentativeDecl(*CurrentD))
- break;
-
- ++FirstD;
- ++CurrentD;
- }
-
- if (FirstD == FirstPath->Decls.end() &&
- CurrentD == Path->Decls.end())
- continue;
- }
+ //
+ // FIXME: The language rule says that this applies irrespective of
+ // whether the sets contain only static members.
+ if (HasOnlyStaticMembers(Path->Decls) &&
+ HasSameDeclarations(Paths.begin()->Decls, Path->Decls))
+ continue;
R.setAmbiguousBaseSubobjectTypes(Paths);
return true;
}
+ // FIXME: This language rule no longer exists. Checking for ambiguous base
+ // subobjects should be done as part of formation of a class member access
+ // expression (when converting the object parameter to the member's type).
if (SubobjectNumber != PathElement.SubobjectNumber) {
// We have a different subobject of the same type.
@@ -2333,7 +2337,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// A static member, a nested type or an enumerator defined in
// a base class T can unambiguously be found even if an object
// has more than one base class subobject of type T.
- if (HasOnlyStaticMembers(Path->Decls.begin(), Path->Decls.end()))
+ if (HasOnlyStaticMembers(Path->Decls))
continue;
// We have found a nonstatic member name in multiple, distinct
@@ -2348,7 +2352,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
for (auto *D : Paths.front().Decls) {
AccessSpecifier AS = CXXRecordDecl::MergeAccess(SubobjectAccess,
D->getAccess());
- R.addDecl(D, AS);
+ if (NamedDecl *ND = R.getAcceptableDecl(D))
+ R.addDecl(ND, AS);
}
R.resolveKind();
return true;
@@ -2504,13 +2509,23 @@ void Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
<< Name << LookupRange;
CXXBasePaths *Paths = Result.getBasePaths();
- std::set<Decl *> DeclsPrinted;
+ std::set<const NamedDecl *> DeclsPrinted;
for (CXXBasePaths::paths_iterator Path = Paths->begin(),
PathEnd = Paths->end();
Path != PathEnd; ++Path) {
- Decl *D = Path->Decls.front();
- if (DeclsPrinted.insert(D).second)
- Diag(D->getLocation(), diag::note_ambiguous_member_found);
+ const NamedDecl *D = Path->Decls.front();
+ if (!D->isInIdentifierNamespace(Result.getIdentifierNamespace()))
+ continue;
+ if (DeclsPrinted.insert(D).second) {
+ if (const auto *TD = dyn_cast<TypedefNameDecl>(D->getUnderlyingDecl()))
+ Diag(D->getLocation(), diag::note_ambiguous_member_type_found)
+ << TD->getUnderlyingType();
+ else if (const auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl()))
+ Diag(D->getLocation(), diag::note_ambiguous_member_type_found)
+ << Context.getTypeDeclType(TD);
+ else
+ Diag(D->getLocation(), diag::note_ambiguous_member_found);
+ }
}
break;
}
@@ -2981,7 +2996,6 @@ ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II,
}
void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
- QualType T1, QualType T2,
UnresolvedSetImpl &Functions) {
// C++ [over.match.oper]p3:
// -- The set of non-member candidates is the result of the
@@ -3319,9 +3333,9 @@ CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) {
/// and filter the results to the appropriate set for the given argument types.
Sema::LiteralOperatorLookupResult
Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
- ArrayRef<QualType> ArgTys,
- bool AllowRaw, bool AllowTemplate,
- bool AllowStringTemplate, bool DiagnoseMissing) {
+ ArrayRef<QualType> ArgTys, bool AllowRaw,
+ bool AllowTemplate, bool AllowStringTemplatePack,
+ bool DiagnoseMissing, StringLiteral *StringLit) {
LookupName(R, S);
assert(R.getResultKind() != LookupResult::Ambiguous &&
"literal operator lookup can't be ambiguous");
@@ -3329,10 +3343,11 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
// Filter the lookup results appropriately.
LookupResult::Filter F = R.makeFilter();
+ bool AllowCooked = true;
bool FoundRaw = false;
bool FoundTemplate = false;
- bool FoundStringTemplate = false;
- bool FoundExactMatch = false;
+ bool FoundStringTemplatePack = false;
+ bool FoundCooked = false;
while (F.hasNext()) {
Decl *D = F.next();
@@ -3347,19 +3362,19 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
bool IsRaw = false;
bool IsTemplate = false;
- bool IsStringTemplate = false;
- bool IsExactMatch = false;
+ bool IsStringTemplatePack = false;
+ bool IsCooked = false;
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->getNumParams() == 1 &&
FD->getParamDecl(0)->getType()->getAs<PointerType>())
IsRaw = true;
else if (FD->getNumParams() == ArgTys.size()) {
- IsExactMatch = true;
+ IsCooked = true;
for (unsigned ArgIdx = 0; ArgIdx != ArgTys.size(); ++ArgIdx) {
QualType ParamTy = FD->getParamDecl(ArgIdx)->getType();
if (!Context.hasSameUnqualifiedType(ArgTys[ArgIdx], ParamTy)) {
- IsExactMatch = false;
+ IsCooked = false;
break;
}
}
@@ -3367,29 +3382,59 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
}
if (FunctionTemplateDecl *FD = dyn_cast<FunctionTemplateDecl>(D)) {
TemplateParameterList *Params = FD->getTemplateParameters();
- if (Params->size() == 1)
+ if (Params->size() == 1) {
IsTemplate = true;
- else
- IsStringTemplate = true;
+ if (!Params->getParam(0)->isTemplateParameterPack() && !StringLit) {
+ // Implied but not stated: user-defined integer and floating literals
+ // only ever use numeric literal operator templates, not templates
+ // taking a parameter of class type.
+ F.erase();
+ continue;
+ }
+
+ // A string literal template is only considered if the string literal
+ // is a well-formed template argument for the template parameter.
+ if (StringLit) {
+ SFINAETrap Trap(*this);
+ SmallVector<TemplateArgument, 1> Checked;
+ TemplateArgumentLoc Arg(TemplateArgument(StringLit), StringLit);
+ if (CheckTemplateArgument(Params->getParam(0), Arg, FD,
+ R.getNameLoc(), R.getNameLoc(), 0,
+ Checked) ||
+ Trap.hasErrorOccurred())
+ IsTemplate = false;
+ }
+ } else {
+ IsStringTemplatePack = true;
+ }
}
- if (IsExactMatch) {
- FoundExactMatch = true;
+ if (AllowTemplate && StringLit && IsTemplate) {
+ FoundTemplate = true;
AllowRaw = false;
- AllowTemplate = false;
- AllowStringTemplate = false;
- if (FoundRaw || FoundTemplate || FoundStringTemplate) {
+ AllowCooked = false;
+ AllowStringTemplatePack = false;
+ if (FoundRaw || FoundCooked || FoundStringTemplatePack) {
+ F.restart();
+ FoundRaw = FoundCooked = FoundStringTemplatePack = false;
+ }
+ } else if (AllowCooked && IsCooked) {
+ FoundCooked = true;
+ AllowRaw = false;
+ AllowTemplate = StringLit;
+ AllowStringTemplatePack = false;
+ if (FoundRaw || FoundTemplate || FoundStringTemplatePack) {
// Go through again and remove the raw and template decls we've
// already found.
F.restart();
- FoundRaw = FoundTemplate = FoundStringTemplate = false;
+ FoundRaw = FoundTemplate = FoundStringTemplatePack = false;
}
} else if (AllowRaw && IsRaw) {
FoundRaw = true;
} else if (AllowTemplate && IsTemplate) {
FoundTemplate = true;
- } else if (AllowStringTemplate && IsStringTemplate) {
- FoundStringTemplate = true;
+ } else if (AllowStringTemplatePack && IsStringTemplatePack) {
+ FoundStringTemplatePack = true;
} else {
F.erase();
}
@@ -3397,10 +3442,15 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
F.done();
+ // Per C++20 [lex.ext]p5, we prefer the template form over the non-template
+ // form for string literal operator templates.
+ if (StringLit && FoundTemplate)
+ return LOLR_Template;
+
// C++11 [lex.ext]p3, p4: If S contains a literal operator with a matching
// parameter type, that is used in preference to a raw literal operator
// or literal operator template.
- if (FoundExactMatch)
+ if (FoundCooked)
return LOLR_Cooked;
// C++11 [lex.ext]p3, p4: S shall contain a raw literal operator or a literal
@@ -3418,15 +3468,15 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
if (FoundTemplate)
return LOLR_Template;
- if (FoundStringTemplate)
- return LOLR_StringTemplate;
+ if (FoundStringTemplatePack)
+ return LOLR_StringTemplatePack;
// Didn't find anything we could use.
if (DiagnoseMissing) {
Diag(R.getNameLoc(), diag::err_ovl_no_viable_literal_operator)
<< R.getLookupName() << (int)ArgTys.size() << ArgTys[0]
<< (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRaw
- << (AllowTemplate || AllowStringTemplate);
+ << (AllowTemplate || AllowStringTemplatePack);
return LOLR_Error;
}
diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index 10de0ca91221..af95b1a93cc4 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -187,7 +187,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
Diag(Path[0].second, diag::err_module_redefinition) << ModuleName;
if (M->DefinitionLoc.isValid())
Diag(M->DefinitionLoc, diag::note_prev_module_definition);
- else if (const auto *FE = M->getASTFile())
+ else if (Optional<FileEntryRef> FE = M->getASTFile())
Diag(M->DefinitionLoc, diag::note_prev_module_definition_from_ast_file)
<< FE->getName();
Mod = M;
diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp
index e301c62dd2c0..fdc30fe6f657 100644
--- a/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/clang/lib/Sema/SemaObjCProperty.cpp
@@ -1464,10 +1464,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue,
PropertyDiagLoc);
MarkDeclRefReferenced(SelfExpr);
- Expr *LoadSelfExpr =
- ImplicitCastExpr::Create(Context, SelfDecl->getType(),
- CK_LValueToRValue, SelfExpr, nullptr,
- VK_RValue);
+ Expr *LoadSelfExpr = ImplicitCastExpr::Create(
+ Context, SelfDecl->getType(), CK_LValueToRValue, SelfExpr, nullptr,
+ VK_RValue, FPOptionsOverride());
Expr *IvarRefExpr =
new (Context) ObjCIvarRefExpr(Ivar,
Ivar->getUsageType(SelfDecl->getType()),
@@ -1528,10 +1527,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue,
PropertyDiagLoc);
MarkDeclRefReferenced(SelfExpr);
- Expr *LoadSelfExpr =
- ImplicitCastExpr::Create(Context, SelfDecl->getType(),
- CK_LValueToRValue, SelfExpr, nullptr,
- VK_RValue);
+ Expr *LoadSelfExpr = ImplicitCastExpr::Create(
+ Context, SelfDecl->getType(), CK_LValueToRValue, SelfExpr, nullptr,
+ VK_RValue, FPOptionsOverride());
Expr *lhs =
new (Context) ObjCIvarRefExpr(Ivar,
Ivar->getUsageType(SelfDecl->getType()),
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 920463da4027..78707484f588 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -35,6 +35,7 @@
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/PointerEmbeddedInt.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Frontend/OpenMP/OMPConstants.h"
#include <set>
@@ -48,7 +49,7 @@ using namespace llvm::omp;
static const Expr *checkMapClauseExpressionBase(
Sema &SemaRef, Expr *E,
OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
- OpenMPClauseKind CKind, bool NoDiagnose);
+ OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
namespace {
/// Default data sharing attributes, which can be applied to directive.
@@ -70,12 +71,15 @@ public:
const Expr *RefExpr = nullptr;
DeclRefExpr *PrivateCopy = nullptr;
SourceLocation ImplicitDSALoc;
+ bool AppliedToPointee = false;
DSAVarData() = default;
DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
const Expr *RefExpr, DeclRefExpr *PrivateCopy,
- SourceLocation ImplicitDSALoc, unsigned Modifier)
+ SourceLocation ImplicitDSALoc, unsigned Modifier,
+ bool AppliedToPointee)
: DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
- PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc) {}
+ PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
+ AppliedToPointee(AppliedToPointee) {}
};
using OperatorOffsetTy =
llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
@@ -99,6 +103,9 @@ private:
/// variable is marked as lastprivate(true) or not (false).
llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
DeclRefExpr *PrivateCopy = nullptr;
+ /// true if the attribute is applied to the pointee, not the variable
+ /// itself.
+ bool AppliedToPointee = false;
};
using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
@@ -153,6 +160,7 @@ private:
OpenMPDirectiveKind Directive = OMPD_unknown;
DeclarationNameInfo DirectiveName;
Scope *CurScope = nullptr;
+ DeclContext *Context = nullptr;
SourceLocation ConstructLoc;
/// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
/// get the data (loop counters etc.) about enclosing loop-based construct.
@@ -184,6 +192,7 @@ private:
llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
UsesAllocatorsDecls;
+ Expr *DeclareMapperVar = nullptr;
SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
Scope *CurScope, SourceLocation Loc)
: Directive(DKind), DirectiveName(Name), CurScope(CurScope),
@@ -510,7 +519,8 @@ public:
/// Adds explicit data sharing attribute to the specified declaration.
void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
- DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0);
+ DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
+ bool AppliedToPointee = false);
/// Adds additional information for the reduction items with the reduction id
/// represented as an operator.
@@ -562,7 +572,8 @@ public:
/// match specified \a CPred predicate in any directive which matches \a DPred
/// predicate.
const DSAVarData
- hasDSA(ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
+ hasDSA(ValueDecl *D,
+ const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
bool FromParent) const;
/// Checks if the specified variables has data-sharing attributes which
@@ -570,15 +581,16 @@ public:
/// matches \a DPred predicate.
const DSAVarData
hasInnermostDSA(ValueDecl *D,
- const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
+ const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
bool FromParent) const;
/// Checks if the specified variables has explicit data-sharing
/// attributes which match specified \a CPred predicate at the specified
/// OpenMP region.
- bool hasExplicitDSA(const ValueDecl *D,
- const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
- unsigned Level, bool NotLastprivate = false) const;
+ bool
+ hasExplicitDSA(const ValueDecl *D,
+ const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
+ unsigned Level, bool NotLastprivate = false) const;
/// Returns true if the directive at level \Level matches in the
/// specified \a DPred predicate.
@@ -908,6 +920,7 @@ public:
const SharingMapTy *Top = getTopOfStackOrNull();
return Top ? Top->CurScope : nullptr;
}
+ void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
SourceLocation getConstructLoc() const {
const SharingMapTy *Top = getTopOfStackOrNull();
return Top ? Top->ConstructLoc : SourceLocation();
@@ -1072,6 +1085,15 @@ public:
return None;
return I->getSecond();
}
+
+ void addDeclareMapperVarRef(Expr *Ref) {
+ SharingMapTy &StackElem = getTopOfStack();
+ StackElem.DeclareMapperVar = Ref;
+ }
+ const Expr *getDeclareMapperVarRef() const {
+ const SharingMapTy *Top = getTopOfStackOrNull();
+ return Top ? Top->DeclareMapperVar : nullptr;
+ }
};
bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
@@ -1175,6 +1197,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
DVar.CKind = Data.Attributes;
DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
DVar.Modifier = Data.Modifier;
+ DVar.AppliedToPointee = Data.AppliedToPointee;
return DVar;
}
@@ -1331,7 +1354,8 @@ const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
}
void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
- DeclRefExpr *PrivateCopy, unsigned Modifier) {
+ DeclRefExpr *PrivateCopy, unsigned Modifier,
+ bool AppliedToPointee) {
D = getCanonicalDecl(D);
if (A == OMPC_threadprivate) {
DSAInfo &Data = Threadprivates[D];
@@ -1355,12 +1379,14 @@ void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
Data.Attributes = A;
Data.RefExpr.setPointerAndInt(E, IsLastprivate);
Data.PrivateCopy = PrivateCopy;
+ Data.AppliedToPointee = AppliedToPointee;
if (PrivateCopy) {
DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
Data.Modifier = Modifier;
Data.Attributes = A;
Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
Data.PrivateCopy = nullptr;
+ Data.AppliedToPointee = AppliedToPointee;
}
}
}
@@ -1470,7 +1496,8 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
"set.");
TaskgroupDescriptor = I->TaskgroupReductionRef;
return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
- Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task);
+ Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
+ /*AppliedToPointee=*/false);
}
return DSAVarData();
}
@@ -1496,7 +1523,8 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
"set.");
TaskgroupDescriptor = I->TaskgroupReductionRef;
return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
- Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task);
+ Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
+ /*AppliedToPointee=*/false);
}
return DSAVarData();
}
@@ -1506,11 +1534,17 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
for (const_iterator E = end(); I != E; ++I) {
if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
isOpenMPTargetExecutionDirective(I->Directive)) {
- Scope *TopScope = I->CurScope ? I->CurScope->getParent() : nullptr;
- Scope *CurScope = getCurScope();
- while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
- CurScope = CurScope->getParent();
- return CurScope != TopScope;
+ if (I->CurScope) {
+ Scope *TopScope = I->CurScope->getParent();
+ Scope *CurScope = getCurScope();
+ while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
+ CurScope = CurScope->getParent();
+ return CurScope != TopScope;
+ }
+ for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
+ if (I->Context == DC)
+ return true;
+ return false;
}
}
return false;
@@ -1665,6 +1699,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
DVar.ImplicitDSALoc = I->DefaultAttrLoc;
DVar.DKind = I->Directive;
DVar.Modifier = Data.Modifier;
+ DVar.AppliedToPointee = Data.AppliedToPointee;
return DVar;
}
}
@@ -1686,7 +1721,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
// listed in a firstprivate clause, even if they are static data members.
DSAVarData DVarTemp = hasInnermostDSA(
D,
- [](OpenMPClauseKind C) {
+ [](OpenMPClauseKind C, bool) {
return C == OMPC_firstprivate || C == OMPC_shared;
},
MatchesAlways, FromParent);
@@ -1715,6 +1750,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
DVar.ImplicitDSALoc = I->DefaultAttrLoc;
DVar.DKind = I->Directive;
DVar.Modifier = Data.Modifier;
+ DVar.AppliedToPointee = Data.AppliedToPointee;
}
return DVar;
@@ -1745,7 +1781,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
const DSAStackTy::DSAVarData
DSAStackTy::hasDSA(ValueDecl *D,
- const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
+ const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
bool FromParent) const {
if (isStackEmpty())
@@ -1761,14 +1797,14 @@ DSAStackTy::hasDSA(ValueDecl *D,
continue;
const_iterator NewI = I;
DSAVarData DVar = getDSA(NewI, D);
- if (I == NewI && CPred(DVar.CKind))
+ if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee))
return DVar;
}
return {};
}
const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
- ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
+ ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
bool FromParent) const {
if (isStackEmpty())
@@ -1782,26 +1818,28 @@ const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
return {};
const_iterator NewI = StartI;
DSAVarData DVar = getDSA(NewI, D);
- return (NewI == StartI && CPred(DVar.CKind)) ? DVar : DSAVarData();
+ return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
+ ? DVar
+ : DSAVarData();
}
bool DSAStackTy::hasExplicitDSA(
- const ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
+ const ValueDecl *D,
+ const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
unsigned Level, bool NotLastprivate) const {
if (getStackSize() <= Level)
return false;
D = getCanonicalDecl(D);
const SharingMapTy &StackElem = getStackElemAtLevel(Level);
auto I = StackElem.SharingMap.find(D);
- if (I != StackElem.SharingMap.end() &&
- I->getSecond().RefExpr.getPointer() &&
- CPred(I->getSecond().Attributes) &&
+ if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
+ CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
(!NotLastprivate || !I->getSecond().RefExpr.getInt()))
return true;
// Check predetermined rules for the loop control variables.
auto LI = StackElem.LCVMap.find(D);
if (LI != StackElem.LCVMap.end())
- return CPred(OMPC_private);
+ return CPred(OMPC_private, /*AppliedToPointee=*/false);
return false;
}
@@ -1859,27 +1897,27 @@ enum class FunctionEmissionStatus {
};
} // anonymous namespace
-Sema::DeviceDiagBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc,
- unsigned DiagID) {
+Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc,
+ unsigned DiagID) {
assert(LangOpts.OpenMP && LangOpts.OpenMPIsDevice &&
"Expected OpenMP device compilation.");
FunctionDecl *FD = getCurFunctionDecl();
- DeviceDiagBuilder::Kind Kind = DeviceDiagBuilder::K_Nop;
+ SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
if (FD) {
FunctionEmissionStatus FES = getEmissionStatus(FD);
switch (FES) {
case FunctionEmissionStatus::Emitted:
- Kind = DeviceDiagBuilder::K_Immediate;
+ Kind = SemaDiagnosticBuilder::K_Immediate;
break;
case FunctionEmissionStatus::Unknown:
Kind = isOpenMPDeviceDelayedContext(*this)
- ? DeviceDiagBuilder::K_Deferred
- : DeviceDiagBuilder::K_Immediate;
+ ? SemaDiagnosticBuilder::K_Deferred
+ : SemaDiagnosticBuilder::K_Immediate;
break;
case FunctionEmissionStatus::TemplateDiscarded:
case FunctionEmissionStatus::OMPDiscarded:
- Kind = DeviceDiagBuilder::K_Nop;
+ Kind = SemaDiagnosticBuilder::K_Nop;
break;
case FunctionEmissionStatus::CUDADiscarded:
llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
@@ -1887,30 +1925,30 @@ Sema::DeviceDiagBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc,
}
}
- return DeviceDiagBuilder(Kind, Loc, DiagID, getCurFunctionDecl(), *this);
+ return SemaDiagnosticBuilder(Kind, Loc, DiagID, getCurFunctionDecl(), *this);
}
-Sema::DeviceDiagBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc,
- unsigned DiagID) {
+Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc,
+ unsigned DiagID) {
assert(LangOpts.OpenMP && !LangOpts.OpenMPIsDevice &&
"Expected OpenMP host compilation.");
FunctionEmissionStatus FES = getEmissionStatus(getCurFunctionDecl());
- DeviceDiagBuilder::Kind Kind = DeviceDiagBuilder::K_Nop;
+ SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
switch (FES) {
case FunctionEmissionStatus::Emitted:
- Kind = DeviceDiagBuilder::K_Immediate;
+ Kind = SemaDiagnosticBuilder::K_Immediate;
break;
case FunctionEmissionStatus::Unknown:
- Kind = DeviceDiagBuilder::K_Deferred;
+ Kind = SemaDiagnosticBuilder::K_Deferred;
break;
case FunctionEmissionStatus::TemplateDiscarded:
case FunctionEmissionStatus::OMPDiscarded:
case FunctionEmissionStatus::CUDADiscarded:
- Kind = DeviceDiagBuilder::K_Nop;
+ Kind = SemaDiagnosticBuilder::K_Nop;
break;
}
- return DeviceDiagBuilder(Kind, Loc, DiagID, getCurFunctionDecl(), *this);
+ return SemaDiagnosticBuilder(Kind, Loc, DiagID, getCurFunctionDecl(), *this);
}
static OpenMPDefaultmapClauseKind
@@ -2047,14 +2085,17 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
// By default, all the data that has a scalar type is mapped by copy
// (except for reduction variables).
// Defaultmap scalar is mutual exclusive to defaultmap pointer
- IsByRef =
- (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
- !Ty->isAnyPointerType()) ||
- !Ty->isScalarType() ||
- DSAStack->isDefaultmapCapturedByRef(
- Level, getVariableCategoryFromDecl(LangOpts, D)) ||
- DSAStack->hasExplicitDSA(
- D, [](OpenMPClauseKind K) { return K == OMPC_reduction; }, Level);
+ IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
+ !Ty->isAnyPointerType()) ||
+ !Ty->isScalarType() ||
+ DSAStack->isDefaultmapCapturedByRef(
+ Level, getVariableCategoryFromDecl(LangOpts, D)) ||
+ DSAStack->hasExplicitDSA(
+ D,
+ [](OpenMPClauseKind K, bool AppliedToPointee) {
+ return K == OMPC_reduction && !AppliedToPointee;
+ },
+ Level);
}
}
@@ -2065,8 +2106,9 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
OMPD_target) ||
!(DSAStack->hasExplicitDSA(
D,
- [](OpenMPClauseKind K) -> bool {
- return K == OMPC_firstprivate;
+ [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
+ return K == OMPC_firstprivate ||
+ (K == OMPC_reduction && AppliedToPointee);
},
Level, /*NotLastprivate=*/true) ||
DSAStack->isUsesAllocatorsDecl(Level, D))) &&
@@ -2078,7 +2120,8 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
// copy
!(DSAStack->getDefaultDSA() == DSA_firstprivate &&
!DSAStack->hasExplicitDSA(
- D, [](OpenMPClauseKind K) { return K != OMPC_unknown; }, Level) &&
+ D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
+ Level) &&
!DSAStack->isLoopControlVariable(D, Level).first);
}
@@ -2141,7 +2184,8 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
!OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
checkDeclIsAllowedInOpenMPTarget(nullptr, VD);
return nullptr;
- } else if (isInOpenMPTargetExecutionDirective()) {
+ }
+ if (isInOpenMPTargetExecutionDirective()) {
// If the declaration is enclosed in a 'declare target' directive,
// then it should not be captured.
//
@@ -2159,6 +2203,7 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
break;
}
}
+ assert(CSI && "Failed to find CapturedRegionScopeInfo");
SmallVector<OpenMPDirectiveKind, 4> Regions;
getOpenMPCaptureRegions(Regions,
DSAStack->getDirective(CSI->OpenMPLevel));
@@ -2194,7 +2239,8 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
return VD ? VD : Info.second;
DSAStackTy::DSAVarData DVarTop =
DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
- if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind))
+ if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
+ (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
// Threadprivate variables must not be captured.
if (isOpenMPThreadPrivate(DVarTop.CKind))
@@ -2202,7 +2248,11 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
// The variable is not private or it is the variable in the directive with
// default(none) clause and not used in any clause.
DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
- D, isOpenMPPrivate, [](OpenMPDirectiveKind) { return true; },
+ D,
+ [](OpenMPClauseKind C, bool AppliedToPointee) {
+ return isOpenMPPrivate(C) && !AppliedToPointee;
+ },
+ [](OpenMPDirectiveKind) { return true; },
DSAStack->isClauseParsingMode());
// Global shared must not be captured.
if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
@@ -2244,7 +2294,11 @@ OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
[](OpenMPDirectiveKind K) { return isOpenMPTaskingDirective(K); },
Level)) {
bool IsTriviallyCopyable =
- D->getType().getNonReferenceType().isTriviallyCopyableType(Context);
+ D->getType().getNonReferenceType().isTriviallyCopyableType(Context) &&
+ !D->getType()
+ .getNonReferenceType()
+ .getCanonicalType()
+ ->getAsCXXRecordDecl();
OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
getOpenMPCaptureRegions(CaptureRegions, DKind);
@@ -2252,7 +2306,8 @@ OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
(IsTriviallyCopyable ||
!isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
if (DSAStack->hasExplicitDSA(
- D, [](OpenMPClauseKind K) { return K == OMPC_firstprivate; },
+ D,
+ [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
Level, /*NotLastprivate=*/true))
return OMPC_firstprivate;
DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
@@ -2273,7 +2328,8 @@ OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
if ((DSAStack->getPossiblyLoopCunter() == D->getCanonicalDecl() ||
DSAStack->isLoopControlVariable(D).first) &&
!DSAStack->hasExplicitDSA(
- D, [](OpenMPClauseKind K) { return K != OMPC_private; }, Level) &&
+ D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
+ Level) &&
!isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
return OMPC_private;
}
@@ -2281,7 +2337,8 @@ OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
DSAStack->isForceVarCapturing() &&
!DSAStack->hasExplicitDSA(
- D, [](OpenMPClauseKind K) { return K == OMPC_copyin; }, Level))
+ D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
+ Level))
return OMPC_private;
}
// User-defined allocators are private since they must be defined in the
@@ -2292,7 +2349,8 @@ OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
return OMPC_private;
return (DSAStack->hasExplicitDSA(
- D, [](OpenMPClauseKind K) { return K == OMPC_private; }, Level) ||
+ D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
+ Level) ||
(DSAStack->isClauseParsingMode() &&
DSAStack->getClauseParsingMode() == OMPC_private) ||
// Consider taskgroup reduction descriptor variable a private
@@ -2317,15 +2375,16 @@ void Sema::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
OpenMPClauseKind OMPC = OMPC_unknown;
for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
const unsigned NewLevel = I - 1;
- if (DSAStack->hasExplicitDSA(D,
- [&OMPC](const OpenMPClauseKind K) {
- if (isOpenMPPrivate(K)) {
- OMPC = K;
- return true;
- }
- return false;
- },
- NewLevel))
+ if (DSAStack->hasExplicitDSA(
+ D,
+ [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
+ if (isOpenMPPrivate(K) && !AppliedToPointee) {
+ OMPC = K;
+ return true;
+ }
+ return false;
+ },
+ NewLevel))
break;
if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
D, NewLevel,
@@ -2368,17 +2427,20 @@ bool Sema::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level,
if (const auto *VD = dyn_cast<VarDecl>(D)) {
if (!VD->hasLocalStorage()) {
+ if (isInOpenMPTargetExecutionDirective())
+ return true;
DSAStackTy::DSAVarData TopDVar =
DSAStack->getTopDSA(D, /*FromParent=*/false);
unsigned NumLevels =
getOpenMPCaptureLevels(DSAStack->getDirective(Level));
if (Level == 0)
return (NumLevels == CaptureLevel + 1) && TopDVar.CKind != OMPC_shared;
- DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level - 1);
- return DVar.CKind != OMPC_shared ||
- isOpenMPGlobalCapturedDecl(
- D, Level - 1,
- getOpenMPCaptureLevels(DSAStack->getDirective(Level - 1)) - 1);
+ do {
+ --Level;
+ DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
+ if (DVar.CKind != OMPC_shared)
+ return true;
+ } while (Level > 0);
}
}
return true;
@@ -2388,10 +2450,6 @@ void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }
void Sema::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,
OMPTraitInfo &TI) {
- if (!OMPDeclareVariantScopes.empty()) {
- Diag(Loc, diag::warn_nested_declare_variant);
- return;
- }
OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
}
@@ -2424,7 +2482,7 @@ void Sema::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
StringRef HostDevTy =
getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
- Diag(FD->getAttr<OMPDeclareTargetDeclAttr>()->getLocation(),
+ Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
diag::note_omp_marked_device_type_here)
<< HostDevTy;
return;
@@ -2435,7 +2493,7 @@ void Sema::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
- Diag(FD->getAttr<OMPDeclareTargetDeclAttr>()->getLocation(),
+ Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
diag::note_omp_marked_device_type_here)
<< NoHostDevTy;
}
@@ -3138,6 +3196,64 @@ Sema::ActOnOpenMPRequiresDirective(SourceLocation Loc,
return DeclGroupPtrTy::make(DeclGroupRef(D));
}
+void Sema::ActOnOpenMPAssumesDirective(SourceLocation Loc,
+ OpenMPDirectiveKind DKind,
+ ArrayRef<StringRef> Assumptions,
+ bool SkippedClauses) {
+ if (!SkippedClauses && Assumptions.empty())
+ Diag(Loc, diag::err_omp_no_clause_for_directive)
+ << llvm::omp::getAllAssumeClauseOptions()
+ << llvm::omp::getOpenMPDirectiveName(DKind);
+
+ auto *AA = AssumptionAttr::Create(Context, llvm::join(Assumptions, ","), Loc);
+ if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
+ OMPAssumeScoped.push_back(AA);
+ return;
+ }
+
+ // Global assumes without assumption clauses are ignored.
+ if (Assumptions.empty())
+ return;
+
+ assert(DKind == llvm::omp::Directive::OMPD_assumes &&
+ "Unexpected omp assumption directive!");
+ OMPAssumeGlobal.push_back(AA);
+
+ // The OMPAssumeGlobal scope above will take care of new declarations but
+ // we also want to apply the assumption to existing ones, e.g., to
+ // declarations in included headers. To this end, we traverse all existing
+ // declaration contexts and annotate function declarations here.
+ SmallVector<DeclContext *, 8> DeclContexts;
+ auto *Ctx = CurContext;
+ while (Ctx->getLexicalParent())
+ Ctx = Ctx->getLexicalParent();
+ DeclContexts.push_back(Ctx);
+ while (!DeclContexts.empty()) {
+ DeclContext *DC = DeclContexts.pop_back_val();
+ for (auto *SubDC : DC->decls()) {
+ if (SubDC->isInvalidDecl())
+ continue;
+ if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
+ DeclContexts.push_back(CTD->getTemplatedDecl());
+ for (auto *S : CTD->specializations())
+ DeclContexts.push_back(S);
+ continue;
+ }
+ if (auto *DC = dyn_cast<DeclContext>(SubDC))
+ DeclContexts.push_back(DC);
+ if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
+ F->addAttr(AA);
+ continue;
+ }
+ }
+ }
+}
+
+void Sema::ActOnOpenMPEndAssumesDirective() {
+ assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
+ OMPAssumeScoped.pop_back();
+}
+
OMPRequiresDecl *Sema::CheckOMPRequiresDecl(SourceLocation Loc,
ArrayRef<OMPClause *> ClauseList) {
/// For target specific clauses, the requires directive cannot be
@@ -3249,6 +3365,14 @@ getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,
case OMPC_DEFAULTMAP_MODIFIER_tofrom:
Kind = OMPC_MAP_tofrom;
break;
+ case OMPC_DEFAULTMAP_MODIFIER_present:
+ // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
+ // If implicit-behavior is present, each variable referenced in the
+ // construct in the category specified by variable-category is treated as if
+ // it had been listed in a map clause with the map-type of alloc and
+ // map-type-modifier of present.
+ Kind = OMPC_MAP_alloc;
+ break;
case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
case OMPC_DEFAULTMAP_MODIFIER_last:
llvm_unreachable("Unexpected defaultmap implicit behavior");
@@ -3275,8 +3399,11 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
bool ErrorFound = false;
bool TryCaptureCXXThisMembers = false;
CapturedStmt *CS = nullptr;
+ const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_pointer + 1;
llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
- llvm::SmallVector<Expr *, 4> ImplicitMap[OMPC_MAP_delete];
+ llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete];
+ llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
+ ImplicitMapModifier[DefaultmapKindNum];
Sema::VarsWithInheritedDSAType VarsWithInheritedDSA;
llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
@@ -3284,6 +3411,13 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
// Check implicitly captured variables.
if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
return;
+ if (S->getDirectiveKind() == OMPD_atomic ||
+ S->getDirectiveKind() == OMPD_critical ||
+ S->getDirectiveKind() == OMPD_section ||
+ S->getDirectiveKind() == OMPD_master) {
+ Visit(S->getAssociatedStmt());
+ return;
+ }
visitSubCaptures(S->getInnermostCapturedStmt());
// Try to capture inner this->member references to generate correct mappings
// and diagnostics.
@@ -3405,6 +3539,18 @@ public:
}
}
}
+ if (SemaRef.getLangOpts().OpenMP > 50) {
+ bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
+ OMPC_DEFAULTMAP_MODIFIER_present;
+ if (IsModifierPresent) {
+ if (llvm::find(ImplicitMapModifier[ClauseKind],
+ OMPC_MAP_MODIFIER_present) ==
+ std::end(ImplicitMapModifier[ClauseKind])) {
+ ImplicitMapModifier[ClauseKind].push_back(
+ OMPC_MAP_MODIFIER_present);
+ }
+ }
+ }
if (isOpenMPTargetExecutionDirective(DKind) &&
!Stack->isLoopControlVariable(VD).first) {
@@ -3445,7 +3591,7 @@ public:
Stack->getDefaultmapModifier(ClauseKind);
OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
- ImplicitMap[Kind].emplace_back(E);
+ ImplicitMap[ClauseKind][Kind].emplace_back(E);
}
return;
}
@@ -3456,7 +3602,10 @@ public:
// enclosing worksharing or parallel construct may not be accessed in an
// explicit task.
DVar = Stack->hasInnermostDSA(
- VD, [](OpenMPClauseKind C) { return C == OMPC_reduction; },
+ VD,
+ [](OpenMPClauseKind C, bool AppliedToPointee) {
+ return C == OMPC_reduction && !AppliedToPointee;
+ },
[](OpenMPDirectiveKind K) {
return isOpenMPParallelDirective(K) ||
isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
@@ -3529,9 +3678,11 @@ public:
OpenMPDefaultmapClauseModifier Modifier =
Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
+ OpenMPDefaultmapClauseKind ClauseKind =
+ getVariableCategoryFromDecl(SemaRef.getLangOpts(), FD);
OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
Modifier, /*IsAggregateOrDeclareTarget*/ true);
- ImplicitMap[Kind].emplace_back(E);
+ ImplicitMap[ClauseKind][Kind].emplace_back(E);
return;
}
@@ -3541,7 +3692,10 @@ public:
// enclosing worksharing or parallel construct may not be accessed in
// an explicit task.
DVar = Stack->hasInnermostDSA(
- FD, [](OpenMPClauseKind C) { return C == OMPC_reduction; },
+ FD,
+ [](OpenMPClauseKind C, bool AppliedToPointee) {
+ return C == OMPC_reduction && !AppliedToPointee;
+ },
[](OpenMPDirectiveKind K) {
return isOpenMPParallelDirective(K) ||
isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
@@ -3570,6 +3724,7 @@ public:
if (isOpenMPTargetExecutionDirective(DKind)) {
OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
+ Stack->getCurrentDirective(),
/*NoDiagnose=*/true))
return;
const auto *VD = cast<ValueDecl>(
@@ -3619,7 +3774,8 @@ public:
// Skip analysis of arguments of implicitly defined map clause for target
// directives.
if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
- C->isImplicit())) {
+ C->isImplicit() &&
+ !isOpenMPTaskingDirective(Stack->getCurrentDirective()))) {
for (Stmt *CC : C->children()) {
if (CC)
Visit(CC);
@@ -3662,8 +3818,13 @@ public:
ArrayRef<Expr *> getImplicitFirstprivate() const {
return ImplicitFirstprivate;
}
- ArrayRef<Expr *> getImplicitMap(OpenMPDefaultmapClauseKind Kind) const {
- return ImplicitMap[Kind];
+ ArrayRef<Expr *> getImplicitMap(OpenMPDefaultmapClauseKind DK,
+ OpenMPMapClauseKind MK) const {
+ return ImplicitMap[DK][MK];
+ }
+ ArrayRef<OpenMPMapModifierKind>
+ getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const {
+ return ImplicitMapModifier[Kind];
}
const Sema::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
return VarsWithInheritedDSA;
@@ -3784,19 +3945,20 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
/*OpenMPCaptureLevel=*/1);
break;
}
+ case OMPD_atomic:
+ case OMPD_critical:
+ case OMPD_section:
+ case OMPD_master:
+ break;
case OMPD_simd:
case OMPD_for:
case OMPD_for_simd:
case OMPD_sections:
- case OMPD_section:
case OMPD_single:
- case OMPD_master:
- case OMPD_critical:
case OMPD_taskgroup:
case OMPD_distribute:
case OMPD_distribute_simd:
case OMPD_ordered:
- case OMPD_atomic:
case OMPD_target_data: {
Sema::CapturedParamNameType Params[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
@@ -4088,6 +4250,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
default:
llvm_unreachable("Unknown OpenMP directive");
}
+ DSAStack->setContext(CurContext);
}
int Sema::getNumberOfConstructScopes(unsigned Level) const {
@@ -4125,6 +4288,7 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
if (!WithInit)
CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
S.CurContext->addHiddenDecl(CED);
+ Sema::TentativeAnalysisScope Trap(S);
S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
return CED;
}
@@ -4262,6 +4426,12 @@ static bool checkOrderedOrderSpecified(Sema &S,
StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
ArrayRef<OMPClause *> Clauses) {
+ if (DSAStack->getCurrentDirective() == OMPD_atomic ||
+ DSAStack->getCurrentDirective() == OMPD_critical ||
+ DSAStack->getCurrentDirective() == OMPD_section ||
+ DSAStack->getCurrentDirective() == OMPD_master)
+ return S;
+
bool ErrorFound = false;
CaptureRegionUnwinderRAII CaptureRegionUnwinder(
*this, ErrorFound, DSAStack->getCurrentDirective());
@@ -4975,7 +5145,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
VarsWithInheritedDSAType VarsWithInheritedDSA;
bool ErrorFound = false;
ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
- if (AStmt && !CurContext->isDependentContext()) {
+ if (AStmt && !CurContext->isDependentContext() && Kind != OMPD_atomic &&
+ Kind != OMPD_critical && Kind != OMPD_section && Kind != OMPD_master) {
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
// Check default data sharing attributes for referenced variables.
@@ -5004,11 +5175,33 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
SmallVector<Expr *, 4> ImplicitFirstprivates(
DSAChecker.getImplicitFirstprivate().begin(),
DSAChecker.getImplicitFirstprivate().end());
- SmallVector<Expr *, 4> ImplicitMaps[OMPC_MAP_delete];
- for (unsigned I = 0; I < OMPC_MAP_delete; ++I) {
- ArrayRef<Expr *> ImplicitMap =
- DSAChecker.getImplicitMap(static_cast<OpenMPDefaultmapClauseKind>(I));
- ImplicitMaps[I].append(ImplicitMap.begin(), ImplicitMap.end());
+ const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_pointer + 1;
+ SmallVector<Expr *, 4> ImplicitMaps[DefaultmapKindNum][OMPC_MAP_delete];
+ SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
+ ImplicitMapModifiers[DefaultmapKindNum];
+ SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
+ ImplicitMapModifiersLoc[DefaultmapKindNum];
+ // Get the original location of present modifier from Defaultmap clause.
+ SourceLocation PresentModifierLocs[DefaultmapKindNum];
+ for (OMPClause *C : Clauses) {
+ if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
+ if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
+ PresentModifierLocs[DMC->getDefaultmapKind()] =
+ DMC->getDefaultmapModifierLoc();
+ }
+ for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) {
+ auto Kind = static_cast<OpenMPDefaultmapClauseKind>(VC);
+ for (unsigned I = 0; I < OMPC_MAP_delete; ++I) {
+ ArrayRef<Expr *> ImplicitMap = DSAChecker.getImplicitMap(
+ Kind, static_cast<OpenMPMapClauseKind>(I));
+ ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end());
+ }
+ ArrayRef<OpenMPMapModifierKind> ImplicitModifier =
+ DSAChecker.getImplicitMapModifier(Kind);
+ ImplicitMapModifiers[VC].append(ImplicitModifier.begin(),
+ ImplicitModifier.end());
+ std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]),
+ ImplicitModifier.size(), PresentModifierLocs[VC]);
}
// Mark taskgroup task_reduction descriptors as implicitly firstprivate.
for (OMPClause *C : Clauses) {
@@ -5034,23 +5227,26 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
ErrorFound = true;
}
}
- int ClauseKindCnt = -1;
- for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps) {
- ++ClauseKindCnt;
- if (ImplicitMap.empty())
- continue;
- CXXScopeSpec MapperIdScopeSpec;
- DeclarationNameInfo MapperId;
- auto Kind = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
- if (OMPClause *Implicit = ActOnOpenMPMapClause(
- llvm::None, llvm::None, MapperIdScopeSpec, MapperId, Kind,
- /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
- ImplicitMap, OMPVarListLocTy())) {
- ClausesWithImplicit.emplace_back(Implicit);
- ErrorFound |=
- cast<OMPMapClause>(Implicit)->varlist_size() != ImplicitMap.size();
- } else {
- ErrorFound = true;
+ for (unsigned I = 0, E = DefaultmapKindNum; I < E; ++I) {
+ int ClauseKindCnt = -1;
+ for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps[I]) {
+ ++ClauseKindCnt;
+ if (ImplicitMap.empty())
+ continue;
+ CXXScopeSpec MapperIdScopeSpec;
+ DeclarationNameInfo MapperId;
+ auto Kind = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
+ if (OMPClause *Implicit = ActOnOpenMPMapClause(
+ ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I],
+ MapperIdScopeSpec, MapperId, Kind, /*IsMapTypeImplicit=*/true,
+ SourceLocation(), SourceLocation(), ImplicitMap,
+ OMPVarListLocTy())) {
+ ClausesWithImplicit.emplace_back(Implicit);
+ ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
+ ImplicitMap.size();
+ } else {
+ ErrorFound = true;
+ }
}
}
}
@@ -5760,7 +5956,8 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
.get();
if (NewStep)
- NewStep = VerifyIntegerConstantExpression(NewStep).get();
+ NewStep =
+ VerifyIntegerConstantExpression(NewStep, /*FIXME*/ AllowFold).get();
}
NewSteps.push_back(NewStep);
}
@@ -5798,12 +5995,45 @@ static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
FD->setParams(Params);
}
+void Sema::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) {
+ if (D->isInvalidDecl())
+ return;
+ FunctionDecl *FD = nullptr;
+ if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
+ FD = UTemplDecl->getTemplatedDecl();
+ else
+ FD = cast<FunctionDecl>(D);
+ assert(FD && "Expected a function declaration!");
+
+ // If we are intantiating templates we do *not* apply scoped assumptions but
+ // only global ones. We apply scoped assumption to the template definition
+ // though.
+ if (!inTemplateInstantiation()) {
+ for (AssumptionAttr *AA : OMPAssumeScoped)
+ FD->addAttr(AA);
+ }
+ for (AssumptionAttr *AA : OMPAssumeGlobal)
+ FD->addAttr(AA);
+}
+
Sema::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
: TI(&TI), NameSuffix(TI.getMangledName()) {}
-FunctionDecl *
-Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S,
- Declarator &D) {
+void Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
+ Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
+ SmallVectorImpl<FunctionDecl *> &Bases) {
+ if (!D.getIdentifier())
+ return;
+
+ OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
+
+ // Template specialization is an extension, check if we do it.
+ bool IsTemplated = !TemplateParamLists.empty();
+ if (IsTemplated &
+ !DVScope.TI->isExtensionActive(
+ llvm::omp::TraitProperty::implementation_extension_allow_templates))
+ return;
+
IdentifierInfo *BaseII = D.getIdentifier();
LookupResult Lookup(*this, DeclarationName(BaseII), D.getIdentifierLoc(),
LookupOrdinaryName);
@@ -5812,12 +6042,18 @@ Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S,
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType FType = TInfo->getType();
- bool IsConstexpr = D.getDeclSpec().getConstexprSpecifier() == CSK_constexpr;
- bool IsConsteval = D.getDeclSpec().getConstexprSpecifier() == CSK_consteval;
+ bool IsConstexpr =
+ D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
+ bool IsConsteval =
+ D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
- FunctionDecl *BaseFD = nullptr;
for (auto *Candidate : Lookup) {
- auto *UDecl = dyn_cast<FunctionDecl>(Candidate->getUnderlyingDecl());
+ auto *CandidateDecl = Candidate->getUnderlyingDecl();
+ FunctionDecl *UDecl = nullptr;
+ if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl))
+ UDecl = cast<FunctionTemplateDecl>(CandidateDecl)->getTemplatedDecl();
+ else if (!IsTemplated)
+ UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
if (!UDecl)
continue;
@@ -5828,22 +6064,32 @@ Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S,
if (UDecl->isConsteval() && !IsConsteval)
continue;
- QualType NewType = Context.mergeFunctionTypes(
- FType, UDecl->getType(), /* OfBlockPointer */ false,
- /* Unqualified */ false, /* AllowCXX */ true);
- if (NewType.isNull())
- continue;
+ QualType UDeclTy = UDecl->getType();
+ if (!UDeclTy->isDependentType()) {
+ QualType NewType = Context.mergeFunctionTypes(
+ FType, UDeclTy, /* OfBlockPointer */ false,
+ /* Unqualified */ false, /* AllowCXX */ true);
+ if (NewType.isNull())
+ continue;
+ }
// Found a base!
- BaseFD = UDecl;
- break;
- }
- if (!BaseFD) {
- BaseFD = cast<FunctionDecl>(ActOnDeclarator(S, D));
- BaseFD->setImplicit(true);
+ Bases.push_back(UDecl);
+ }
+
+ bool UseImplicitBase = !DVScope.TI->isExtensionActive(
+ llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
+ // If no base was found we create a declaration that we use as base.
+ if (Bases.empty() && UseImplicitBase) {
+ D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
+ Decl *BaseD = HandleDeclarator(S, D, TemplateParamLists);
+ BaseD->setImplicit(true);
+ if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
+ Bases.push_back(BaseTemplD->getTemplatedDecl());
+ else
+ Bases.push_back(cast<FunctionDecl>(BaseD));
}
- OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
std::string MangledName;
MangledName += D.getIdentifier()->getName();
MangledName += getOpenMPVariantManglingSeparatorStr();
@@ -5852,17 +6098,21 @@ Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S,
VariantII.setMangledOpenMPVariantName(true);
D.SetIdentifier(&VariantII, D.getBeginLoc());
- return BaseFD;
}
void Sema::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
- FunctionDecl *FD, FunctionDecl *BaseFD) {
+ Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) {
// Do not mark function as is used to prevent its emission if this is the
// only place where it is used.
EnterExpressionEvaluationContext Unevaluated(
*this, Sema::ExpressionEvaluationContext::Unevaluated);
- Expr *VariantFuncRef = DeclRefExpr::Create(
+ FunctionDecl *FD = nullptr;
+ if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
+ FD = UTemplDecl->getTemplatedDecl();
+ else
+ FD = cast<FunctionDecl>(D);
+ auto *VariantFuncRef = DeclRefExpr::Create(
Context, NestedNameSpecifierLoc(), SourceLocation(), FD,
/* RefersToEnclosingVariableOrCapture */ false,
/* NameLoc */ FD->getLocation(), FD->getType(), ExprValueKind::VK_RValue);
@@ -5870,7 +6120,8 @@ void Sema::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
Context, VariantFuncRef, DVScope.TI);
- BaseFD->addAttr(OMPDeclareVariantA);
+ for (FunctionDecl *BaseFD : Bases)
+ BaseFD->addAttr(OMPDeclareVariantA);
}
ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
@@ -5891,8 +6142,17 @@ ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
return Call;
ASTContext &Context = getASTContext();
- OMPContext OMPCtx(getLangOpts().OpenMPIsDevice,
- Context.getTargetInfo().getTriple());
+ std::function<void(StringRef)> DiagUnknownTrait = [this,
+ CE](StringRef ISATrait) {
+ // TODO Track the selector locations in a way that is accessible here to
+ // improve the diagnostic location.
+ Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
+ << ISATrait;
+ };
+ TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
+ getCurFunctionDecl());
+
+ QualType CalleeFnType = CalleeFnDecl->getType();
SmallVector<Expr *, 4> Exprs;
SmallVector<VariantMatchInfo, 4> VMIs;
@@ -5904,7 +6164,8 @@ ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
VariantMatchInfo VMI;
OMPTraitInfo &TI = A->getTraitInfo();
TI.getAsVariantMatchInfo(Context, VMI);
- if (!isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ false))
+ if (!isVariantApplicableInContext(VMI, OMPCtx,
+ /* DeviceSetOnly */ false))
continue;
VMIs.push_back(VMI);
@@ -5945,8 +6206,19 @@ ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
}
NewCall = BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs, RParenLoc,
ExecConfig);
- if (NewCall.isUsable())
- break;
+ if (NewCall.isUsable()) {
+ if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
+ FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
+ QualType NewType = Context.mergeFunctionTypes(
+ CalleeFnType, NewCalleeFnDecl->getType(),
+ /* OfBlockPointer */ false,
+ /* Unqualified */ false, /* AllowCXX */ true);
+ if (!NewType.isNull())
+ break;
+ // Don't use the call if the function type was not compatible.
+ NewCall = nullptr;
+ }
+ }
}
VMIs.erase(VMIs.begin() + BestIdx);
@@ -6027,8 +6299,7 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
// Deal with non-constant score and user condition expressions.
auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
bool IsScore) -> bool {
- llvm::APSInt Result;
- if (!E || E->isIntegerConstantExpr(Result, Context))
+ if (!E || E->isIntegerConstantExpr(Context))
return false;
if (IsScore) {
@@ -6051,7 +6322,7 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
// Convert VariantRef expression to the type of the original function to
// resolve possible conflicts.
- ExprResult VariantRefCast;
+ ExprResult VariantRefCast = VariantRef;
if (LangOpts.CPlusPlus) {
QualType FnPtrType;
auto *Method = dyn_cast<CXXMethodDecl>(FD);
@@ -6076,25 +6347,27 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
} else {
FnPtrType = Context.getPointerType(FD->getType());
}
- ImplicitConversionSequence ICS =
- TryImplicitConversion(VariantRef, FnPtrType.getUnqualifiedType(),
- /*SuppressUserConversions=*/false,
- AllowedExplicit::None,
- /*InOverloadResolution=*/false,
- /*CStyle=*/false,
- /*AllowObjCWritebackConversion=*/false);
- if (ICS.isFailure()) {
- Diag(VariantRef->getExprLoc(),
- diag::err_omp_declare_variant_incompat_types)
- << VariantRef->getType()
- << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
- << VariantRef->getSourceRange();
- return None;
+ QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
+ if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
+ ImplicitConversionSequence ICS = TryImplicitConversion(
+ VariantRef, FnPtrType.getUnqualifiedType(),
+ /*SuppressUserConversions=*/false, AllowedExplicit::None,
+ /*InOverloadResolution=*/false,
+ /*CStyle=*/false,
+ /*AllowObjCWritebackConversion=*/false);
+ if (ICS.isFailure()) {
+ Diag(VariantRef->getExprLoc(),
+ diag::err_omp_declare_variant_incompat_types)
+ << VariantRef->getType()
+ << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
+ << VariantRef->getSourceRange();
+ return None;
+ }
+ VariantRefCast = PerformImplicitConversion(
+ VariantRef, FnPtrType.getUnqualifiedType(), AA_Converting);
+ if (!VariantRefCast.isUsable())
+ return None;
}
- VariantRefCast = PerformImplicitConversion(
- VariantRef, FnPtrType.getUnqualifiedType(), AA_Converting);
- if (!VariantRefCast.isUsable())
- return None;
// Drop previously built artificial addr_of unary op for member functions.
if (Method && !Method->isStatic()) {
Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
@@ -6102,8 +6375,6 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
PossibleAddrOfVariantRef->IgnoreImplicit()))
VariantRefCast = UO->getSubExpr();
}
- } else {
- VariantRefCast = VariantRef;
}
ExprResult ER = CheckPlaceholderExpr(VariantRefCast.get());
@@ -6514,14 +6785,14 @@ bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
// loop. If test-expr is of form b relational-op var and relational-op is
// > or >= then incr-expr must cause var to increase on each iteration of
// the loop.
- llvm::APSInt Result;
- bool IsConstant = NewStep->isIntegerConstantExpr(Result, SemaRef.Context);
+ Optional<llvm::APSInt> Result =
+ NewStep->getIntegerConstantExpr(SemaRef.Context);
bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
bool IsConstNeg =
- IsConstant && Result.isSigned() && (Subtract != Result.isNegative());
+ Result && Result->isSigned() && (Subtract != Result->isNegative());
bool IsConstPos =
- IsConstant && Result.isSigned() && (Subtract == Result.isNegative());
- bool IsConstZero = IsConstant && !Result.getBoolValue();
+ Result && Result->isSigned() && (Subtract == Result->isNegative());
+ bool IsConstZero = Result && !Result->getBoolValue();
// != with increment is treated as <; != with decrement is treated as >
if (!TestIsLessOp.hasValue())
@@ -6969,9 +7240,16 @@ calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures);
if (!NewStep.isUsable())
return nullptr;
- llvm::APSInt LRes, URes, SRes;
- bool IsLowerConst = Lower->isIntegerConstantExpr(LRes, SemaRef.Context);
- bool IsStepConst = Step->isIntegerConstantExpr(SRes, SemaRef.Context);
+ llvm::APSInt LRes, SRes;
+ bool IsLowerConst = false, IsStepConst = false;
+ if (Optional<llvm::APSInt> Res = Lower->getIntegerConstantExpr(SemaRef.Context)) {
+ LRes = *Res;
+ IsLowerConst = true;
+ }
+ if (Optional<llvm::APSInt> Res = Step->getIntegerConstantExpr(SemaRef.Context)) {
+ SRes = *Res;
+ IsStepConst = true;
+ }
bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
((!TestIsStrictOp && LRes.isNonNegative()) ||
(TestIsStrictOp && LRes.isStrictlyPositive()));
@@ -7004,7 +7282,12 @@ calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
}
NeedToReorganize = NoNeedToConvert;
}
- bool IsUpperConst = Upper->isIntegerConstantExpr(URes, SemaRef.Context);
+ llvm::APSInt URes;
+ bool IsUpperConst = false;
+ if (Optional<llvm::APSInt> Res = Upper->getIntegerConstantExpr(SemaRef.Context)) {
+ URes = *Res;
+ IsUpperConst = true;
+ }
if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
(!RoundToStep || IsStepConst)) {
unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
@@ -7436,6 +7719,7 @@ std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
if (!Diff.isUsable())
return std::make_pair(nullptr, nullptr);
+ Sema::TentativeAnalysisScope Trap(SemaRef);
Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
if (!Diff.isUsable())
return std::make_pair(nullptr, nullptr);
@@ -7952,9 +8236,9 @@ static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
static bool fitsInto(unsigned Bits, bool Signed, const 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);
+ if (Optional<llvm::APSInt> Result =
+ E->getIntegerConstantExpr(SemaRef.Context))
+ return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
return false;
}
@@ -8227,9 +8511,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// 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);
+ bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
ExprResult CalcLastIteration;
if (!IsConstant) {
ExprResult SaveRef =
@@ -8915,8 +9197,6 @@ StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt,
if (!AStmt)
return StmtError();
- assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
-
setFunctionHasBranchProtectedScope();
DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
@@ -8961,8 +9241,6 @@ StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt,
if (!AStmt)
return StmtError();
- assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
-
setFunctionHasBranchProtectedScope();
return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);
@@ -8974,8 +9252,6 @@ StmtResult Sema::ActOnOpenMPCriticalDirective(
if (!AStmt)
return StmtError();
- assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
-
bool ErrorFound = false;
llvm::APSInt Hint;
SourceLocation HintLoc;
@@ -9693,7 +9969,6 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
if (!AStmt)
return StmtError();
- 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.
@@ -9757,7 +10032,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
<< getOpenMPClauseName(MemOrderKind);
}
- Stmt *Body = CS->getCapturedStmt();
+ Stmt *Body = AStmt;
if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
Body = EWC->getSubExpr();
@@ -12620,15 +12895,16 @@ isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind,
ValExpr = Value.get();
// The expression must evaluate to a non-negative integer value.
- llvm::APSInt Result;
- if (ValExpr->isIntegerConstantExpr(Result, SemaRef.Context) &&
- Result.isSigned() &&
- !((!StrictlyPositive && Result.isNonNegative()) ||
- (StrictlyPositive && Result.isStrictlyPositive()))) {
- SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
- << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
- << ValExpr->getSourceRange();
- return false;
+ if (Optional<llvm::APSInt> Result =
+ ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
+ if (Result->isSigned() &&
+ !((!StrictlyPositive && Result->isNonNegative()) ||
+ (StrictlyPositive && Result->isStrictlyPositive()))) {
+ SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
+ << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
+ << ValExpr->getSourceRange();
+ return false;
+ }
}
if (!BuildCapture)
return true;
@@ -12681,7 +12957,8 @@ ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
return E;
llvm::APSInt Result;
- ExprResult ICE = VerifyIntegerConstantExpression(E, &Result);
+ ExprResult ICE =
+ VerifyIntegerConstantExpression(E, &Result, /*FIXME*/ AllowFold);
if (ICE.isInvalid())
return ExprError();
if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
@@ -13263,9 +13540,9 @@ OMPClause *Sema::ActOnOpenMPScheduleClause(
// OpenMP [2.7.1, Restrictions]
// chunk_size must be a loop invariant integer expression with a positive
// value.
- llvm::APSInt Result;
- if (ValExpr->isIntegerConstantExpr(Result, Context)) {
- if (Result.isSigned() && !Result.isStrictlyPositive()) {
+ if (Optional<llvm::APSInt> Result =
+ ValExpr->getIntegerConstantExpr(Context)) {
+ if (Result->isSigned() && !Result->isStrictlyPositive()) {
Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
<< "schedule" << 1 << ChunkSize->getSourceRange();
return nullptr;
@@ -13522,7 +13799,9 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
DeclarationNameInfo &ReductionOrMapperId, int ExtraModifier,
ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
ArrayRef<SourceLocation> MapTypeModifiersLoc, bool IsMapTypeImplicit,
- SourceLocation ExtraModifierLoc) {
+ SourceLocation ExtraModifierLoc,
+ ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
+ ArrayRef<SourceLocation> MotionModifiersLoc) {
SourceLocation StartLoc = Locs.StartLoc;
SourceLocation LParenLoc = Locs.LParenLoc;
SourceLocation EndLoc = Locs.EndLoc;
@@ -13599,12 +13878,14 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
IsMapTypeImplicit, ExtraModifierLoc, ColonLoc, VarList, Locs);
break;
case OMPC_to:
- Res = ActOnOpenMPToClause(VarList, ReductionOrMapperIdScopeSpec,
- ReductionOrMapperId, Locs);
+ Res = ActOnOpenMPToClause(MotionModifiers, MotionModifiersLoc,
+ ReductionOrMapperIdScopeSpec, ReductionOrMapperId,
+ ColonLoc, VarList, Locs);
break;
case OMPC_from:
- Res = ActOnOpenMPFromClause(VarList, ReductionOrMapperIdScopeSpec,
- ReductionOrMapperId, Locs);
+ Res = ActOnOpenMPFromClause(MotionModifiers, MotionModifiersLoc,
+ ReductionOrMapperIdScopeSpec,
+ ReductionOrMapperId, ColonLoc, VarList, Locs);
break;
case OMPC_use_device_ptr:
Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
@@ -14003,7 +14284,10 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
// from the worksharing construct.
if (isOpenMPTaskingDirective(CurrDir)) {
DVar = DSAStack->hasInnermostDSA(
- D, [](OpenMPClauseKind C) { return C == OMPC_reduction; },
+ D,
+ [](OpenMPClauseKind C, bool AppliedToPointee) {
+ return C == OMPC_reduction && !AppliedToPointee;
+ },
[](OpenMPDirectiveKind K) {
return isOpenMPParallelDirective(K) ||
isOpenMPWorksharingDirective(K) ||
@@ -14296,7 +14580,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(
if (!isOpenMPCapturedDecl(D))
ExprCaptures.push_back(Ref->getDecl());
}
- if (TopDVar.CKind == OMPC_firstprivate ||
+ if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
(!isOpenMPCapturedDecl(D) &&
Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
ExprResult RefRes = DefaultLvalueConversion(Ref);
@@ -14394,7 +14678,11 @@ public:
if (DVar.CKind != OMPC_unknown)
return true;
DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
- VD, isOpenMPPrivate, [](OpenMPDirectiveKind) { return true; },
+ VD,
+ [](OpenMPClauseKind C, bool AppliedToPointee) {
+ return isOpenMPPrivate(C) && !AppliedToPointee;
+ },
+ [](OpenMPDirectiveKind) { return true; },
/*FromParent=*/true);
return DVarPrivate.CKind != OMPC_unknown;
}
@@ -15027,6 +15315,17 @@ static bool actOnOMPReductionKindClause(
continue;
}
}
+ } else {
+ // Threadprivates cannot be shared between threads, so dignose if the base
+ // is a threadprivate variable.
+ DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
+ if (DVar.CKind == OMPC_threadprivate) {
+ S.Diag(ELoc, diag::err_omp_wrong_dsa)
+ << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_reduction);
+ reportOriginalDsa(S, Stack, D, DVar);
+ continue;
+ }
}
// Try to find 'declare reduction' corresponding construct before using
@@ -15153,6 +15452,7 @@ static bool actOnOMPReductionKindClause(
auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
if (DRD->getInitializer()) {
+ S.ActOnUninitializedDecl(PrivateVD);
Init = DRDRef;
RHSVD->setInit(DRDRef);
RHSVD->setInitStyle(VarDecl::CallInit);
@@ -15259,10 +15559,19 @@ static bool actOnOMPReductionKindClause(
llvm_unreachable("Unexpected reduction operation");
}
}
- if (Init && DeclareReductionRef.isUnset())
+ if (Init && DeclareReductionRef.isUnset()) {
S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
- else if (!Init)
+ // Store initializer for single element in private copy. Will be used
+ // during codegen.
+ PrivateVD->setInit(RHSVD->getInit());
+ PrivateVD->setInitStyle(RHSVD->getInitStyle());
+ } else if (!Init) {
S.ActOnUninitializedDecl(RHSVD);
+ // Store initializer for single element in private copy. Will be used
+ // during codegen.
+ PrivateVD->setInit(RHSVD->getInit());
+ PrivateVD->setInitStyle(RHSVD->getInitStyle());
+ }
if (RHSVD->isInvalidDecl())
continue;
if (!RHSVD->hasInit() &&
@@ -15276,10 +15585,6 @@ static bool actOnOMPReductionKindClause(
<< D;
continue;
}
- // Store initializer for single element in private copy. Will be used during
- // codegen.
- PrivateVD->setInit(RHSVD->getInit());
- PrivateVD->setInitStyle(RHSVD->getInitStyle());
DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
ExprResult ReductionOp;
if (DeclareReductionRef.isUsable()) {
@@ -15290,12 +15595,12 @@ static bool actOnOMPReductionKindClause(
if (!BasePath.empty()) {
LHS = S.DefaultLvalueConversion(LHS.get());
RHS = S.DefaultLvalueConversion(RHS.get());
- LHS = ImplicitCastExpr::Create(Context, PtrRedTy,
- CK_UncheckedDerivedToBase, LHS.get(),
- &BasePath, LHS.get()->getValueKind());
- RHS = ImplicitCastExpr::Create(Context, PtrRedTy,
- CK_UncheckedDerivedToBase, RHS.get(),
- &BasePath, RHS.get()->getValueKind());
+ LHS = ImplicitCastExpr::Create(
+ Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
+ LHS.get()->getValueKind(), FPOptionsOverride());
+ RHS = ImplicitCastExpr::Create(
+ Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
+ RHS.get()->getValueKind(), FPOptionsOverride());
}
FunctionProtoType::ExtProtoInfo EPI;
QualType Params[] = {PtrRedTy, PtrRedTy};
@@ -15305,7 +15610,8 @@ static bool actOnOMPReductionKindClause(
S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
Expr *Args[] = {LHS.get(), RHS.get()};
ReductionOp =
- CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc);
+ CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc,
+ S.CurFPFeatureOverrides());
} else {
ReductionOp = S.BuildBinOp(
Stack->getCurScope(), ReductionId.getBeginLoc(), BOK, LHSDRE, RHSDRE);
@@ -15465,7 +15771,8 @@ static bool actOnOMPReductionKindClause(
// correct analysis of in_reduction clauses.
if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
Modifier = OMPC_REDUCTION_task;
- Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier);
+ Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
+ ASE || OASE);
if (Modifier == OMPC_REDUCTION_task &&
(CurrDir == OMPD_taskgroup ||
((isOpenMPParallelDirective(CurrDir) ||
@@ -15736,12 +16043,12 @@ OMPClause *Sema::ActOnOpenMPLinearClause(
// Warn about zero linear step (it would be probably better specified as
// making corresponding variables 'const').
- llvm::APSInt Result;
- bool IsConstant = StepExpr->isIntegerConstantExpr(Result, Context);
- if (IsConstant && !Result.isNegative() && !Result.isStrictlyPositive())
- Diag(StepLoc, diag::warn_omp_linear_step_zero) << Vars[0]
- << (Vars.size() > 1);
- if (!IsConstant && CalcStep.isUsable()) {
+ if (Optional<llvm::APSInt> Result =
+ StepExpr->getIntegerConstantExpr(Context)) {
+ if (!Result->isNegative() && !Result->isStrictlyPositive())
+ Diag(StepLoc, diag::warn_omp_linear_step_zero)
+ << Vars[0] << (Vars.size() > 1);
+ } else if (CalcStep.isUsable()) {
// Calculate the step beforehand instead of doing this on each iteration.
// (This is not used if the number of iterations may be kfold-ed).
CalcStepExpr = CalcStep.get();
@@ -16645,11 +16952,14 @@ namespace {
class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
Sema &SemaRef;
OpenMPClauseKind CKind = OMPC_unknown;
+ OpenMPDirectiveKind DKind = OMPD_unknown;
OMPClauseMappableExprCommon::MappableExprComponentList &Components;
+ bool IsNonContiguous = false;
bool NoDiagnose = false;
const Expr *RelevantExpr = nullptr;
bool AllowUnitySizeArraySection = true;
bool AllowWholeSizeArraySection = true;
+ bool AllowAnotherPtr = true;
SourceLocation ELoc;
SourceRange ERange;
@@ -16674,7 +16984,7 @@ public:
assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
RelevantExpr = DRE;
// Record the component.
- Components.emplace_back(DRE, DRE->getDecl());
+ Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
return true;
}
@@ -16746,7 +17056,7 @@ public:
AllowWholeSizeArraySection = false;
// Record the component.
- Components.emplace_back(ME, FD);
+ Components.emplace_back(ME, FD, IsNonContiguous);
return RelevantExpr || Visit(E);
}
@@ -16784,7 +17094,7 @@ public:
}
// Record the component - we don't have any declaration associated.
- Components.emplace_back(AE, nullptr);
+ Components.emplace_back(AE, nullptr, IsNonContiguous);
return RelevantExpr || Visit(E);
}
@@ -16823,6 +17133,13 @@ public:
// pointer. Otherwise, only unitary sections are accepted.
if (NotWhole || IsPointer)
AllowWholeSizeArraySection = false;
+ } else if (DKind == OMPD_target_update &&
+ SemaRef.getLangOpts().OpenMP >= 50) {
+ if (IsPointer && !AllowAnotherPtr)
+ SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
+ << /*array of unknown bound */ 1;
+ else
+ IsNonContiguous = true;
} else if (AllowUnitySizeArraySection && NotUnity) {
// A unity or whole array section is not allowed and that is not
// compatible with the properties of the current array section.
@@ -16832,6 +17149,9 @@ public:
return false;
}
+ if (IsPointer)
+ AllowAnotherPtr = false;
+
if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
Expr::EvalResult ResultR;
Expr::EvalResult ResultL;
@@ -16857,14 +17177,14 @@ public:
}
// Record the component - we don't have any declaration associated.
- Components.emplace_back(OASE, nullptr);
+ Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
return RelevantExpr || Visit(E);
}
bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
Expr *Base = E->getBase();
// Record the component - we don't have any declaration associated.
- Components.emplace_back(E, nullptr);
+ Components.emplace_back(E, nullptr, IsNonContiguous);
return Visit(Base->IgnoreParenImpCasts());
}
@@ -16877,7 +17197,7 @@ public:
}
if (!RelevantExpr) {
// Record the component if haven't found base decl.
- Components.emplace_back(UO, nullptr);
+ Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
}
return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
}
@@ -16893,7 +17213,7 @@ public:
// know the other subtree is just an offset)
Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
- Components.emplace_back(BO, nullptr);
+ Components.emplace_back(BO, nullptr, false);
assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
"Either LHS or RHS have base decl inside");
@@ -16904,7 +17224,12 @@ public:
bool VisitCXXThisExpr(CXXThisExpr *CTE) {
assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
RelevantExpr = CTE;
- Components.emplace_back(CTE, nullptr);
+ Components.emplace_back(CTE, nullptr, IsNonContiguous);
+ return true;
+ }
+ bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
+ assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
+ Components.emplace_back(COCE, nullptr, IsNonContiguous);
return true;
}
bool VisitStmt(Stmt *) {
@@ -16915,10 +17240,10 @@ public:
return RelevantExpr;
}
explicit MapBaseChecker(
- Sema &SemaRef, OpenMPClauseKind CKind,
+ Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
OMPClauseMappableExprCommon::MappableExprComponentList &Components,
bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
- : SemaRef(SemaRef), CKind(CKind), Components(Components),
+ : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
};
} // namespace
@@ -16930,13 +17255,30 @@ public:
static const Expr *checkMapClauseExpressionBase(
Sema &SemaRef, Expr *E,
OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
- OpenMPClauseKind CKind, bool NoDiagnose) {
+ OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
SourceLocation ELoc = E->getExprLoc();
SourceRange ERange = E->getSourceRange();
- MapBaseChecker Checker(SemaRef, CKind, CurComponents, NoDiagnose, ELoc,
+ MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
ERange);
- if (Checker.Visit(E->IgnoreParens()))
+ if (Checker.Visit(E->IgnoreParens())) {
+ // Check if the highest dimension array section has length specified
+ if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
+ (CKind == OMPC_to || CKind == OMPC_from)) {
+ auto CI = CurComponents.rbegin();
+ auto CE = CurComponents.rend();
+ for (; CI != CE; ++CI) {
+ const auto *OASE =
+ dyn_cast<OMPArraySectionExpr>(CI->getAssociatedExpression());
+ if (!OASE)
+ continue;
+ if (OASE && OASE->getLength())
+ break;
+ SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
+ << ERange;
+ }
+ }
return Checker.getFoundBase();
+ }
return nullptr;
}
@@ -17347,6 +17689,7 @@ static void checkMappableExpressionList(
auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
MapperId.setName(DeclNames.getIdentifier(
&SemaRef.getASTContext().Idents.get("default")));
+ MapperId.setLoc(StartLoc);
}
// Iterators to find the current unresolved mapper expression.
@@ -17413,7 +17756,8 @@ static void checkMappableExpressionList(
// Obtain the array or member expression bases if required. Also, fill the
// components array with all the components identified in the process.
const Expr *BE = checkMapClauseExpressionBase(
- SemaRef, SimpleExpr, CurComponents, CKind, /*NoDiagnose=*/false);
+ SemaRef, SimpleExpr, CurComponents, CKind, DSAS->getCurrentDirective(),
+ /*NoDiagnose=*/false);
if (!BE)
continue;
@@ -17478,6 +17822,7 @@ static void checkMappableExpressionList(
/*CurrentRegionOnly=*/true, CurComponents, CKind))
break;
if (CKind == OMPC_map &&
+ (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
/*CurrentRegionOnly=*/false, CurComponents, CKind))
break;
@@ -17623,9 +17968,9 @@ OMPClause *Sema::ActOnOpenMPMapClause(
OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
- OpenMPMapModifierKind Modifiers[] = {OMPC_MAP_MODIFIER_unknown,
- OMPC_MAP_MODIFIER_unknown,
- OMPC_MAP_MODIFIER_unknown};
+ OpenMPMapModifierKind Modifiers[] = {
+ OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
+ OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown};
SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers];
// Process map-type-modifiers, flag errors for duplicate modifiers.
@@ -17944,10 +18289,10 @@ QualType Sema::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
return MapperType;
}
-OMPDeclareMapperDecl *Sema::ActOnOpenMPDeclareMapperDirectiveStart(
+Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareMapperDirective(
Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
- Decl *PrevDeclInScope) {
+ Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPMapperName,
forRedeclarationInCurContext());
// [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
@@ -18007,48 +18352,51 @@ OMPDeclareMapperDecl *Sema::ActOnOpenMPDeclareMapperDirectiveStart(
Invalid = true;
}
auto *DMD = OMPDeclareMapperDecl::Create(Context, DC, StartLoc, Name,
- MapperType, VN, PrevDMD);
- DC->addDecl(DMD);
+ MapperType, VN, Clauses, PrevDMD);
+ if (S)
+ PushOnScopeChains(DMD, S);
+ else
+ DC->addDecl(DMD);
DMD->setAccess(AS);
if (Invalid)
DMD->setInvalidDecl();
- // Enter new function scope.
- PushFunctionScope();
- setFunctionHasBranchProtectedScope();
-
- CurContext = DMD;
+ auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
+ VD->setDeclContext(DMD);
+ VD->setLexicalDeclContext(DMD);
+ DMD->addDecl(VD);
+ DMD->setMapperVarRef(MapperVarRef);
- return DMD;
+ return DeclGroupPtrTy::make(DeclGroupRef(DMD));
}
-void Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(OMPDeclareMapperDecl *DMD,
- Scope *S,
- QualType MapperType,
- SourceLocation StartLoc,
- DeclarationName VN) {
- VarDecl *VD = buildVarDecl(*this, StartLoc, MapperType, VN.getAsString());
+ExprResult
+Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType,
+ SourceLocation StartLoc,
+ DeclarationName VN) {
+ TypeSourceInfo *TInfo =
+ Context.getTrivialTypeSourceInfo(MapperType, StartLoc);
+ auto *VD = VarDecl::Create(Context, Context.getTranslationUnitDecl(),
+ StartLoc, StartLoc, VN.getAsIdentifierInfo(),
+ MapperType, TInfo, SC_None);
if (S)
- PushOnScopeChains(VD, S);
- else
- DMD->addDecl(VD);
- Expr *MapperVarRefExpr = buildDeclRefExpr(*this, VD, MapperType, StartLoc);
- DMD->setMapperVarRef(MapperVarRefExpr);
+ PushOnScopeChains(VD, S, /*AddToContext=*/false);
+ Expr *E = buildDeclRefExpr(*this, VD, MapperType, StartLoc);
+ DSAStack->addDeclareMapperVarRef(E);
+ return E;
}
-Sema::DeclGroupPtrTy
-Sema::ActOnOpenMPDeclareMapperDirectiveEnd(OMPDeclareMapperDecl *D, Scope *S,
- ArrayRef<OMPClause *> ClauseList) {
- PopDeclContext();
- PopFunctionScopeInfo();
-
- if (D) {
- if (S)
- PushOnScopeChains(D, S, /*AddToContext=*/false);
- D->CreateClauses(Context, ClauseList);
- }
+bool Sema::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const {
+ assert(LangOpts.OpenMP && "Expected OpenMP mode.");
+ const Expr *Ref = DSAStack->getDeclareMapperVarRef();
+ if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref))
+ return VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl();
+ return true;
+}
- return DeclGroupPtrTy::make(DeclGroupRef(D));
+const ValueDecl *Sema::getOpenMPDeclareMapperVarName() const {
+ assert(LangOpts.OpenMP && "Expected OpenMP mode.");
+ return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
}
OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
@@ -18273,9 +18621,9 @@ OMPClause *Sema::ActOnOpenMPDistScheduleClause(
// OpenMP [2.7.1, Restrictions]
// chunk_size must be a loop invariant integer expression with a positive
// value.
- llvm::APSInt Result;
- if (ValExpr->isIntegerConstantExpr(Result, Context)) {
- if (Result.isSigned() && !Result.isStrictlyPositive()) {
+ if (Optional<llvm::APSInt> Result =
+ ValExpr->getIntegerConstantExpr(Context)) {
+ if (Result->isSigned() && !Result->isStrictlyPositive()) {
Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
<< "dist_schedule" << ChunkSize->getSourceRange();
return nullptr;
@@ -18326,20 +18674,38 @@ OMPClause *Sema::ActOnOpenMPDefaultmapClause(
bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
(LangOpts.OpenMP >= 50 && KindLoc.isInvalid());
if (!isDefaultmapKind || !isDefaultmapModifier) {
- std::string ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
+ StringRef KindValue = "'scalar', 'aggregate', 'pointer'";
+ if (LangOpts.OpenMP == 50) {
+ StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
"'firstprivate', 'none', 'default'";
- std::string KindValue = "'scalar', 'aggregate', 'pointer'";
- if (!isDefaultmapKind && isDefaultmapModifier) {
- Diag(KindLoc, diag::err_omp_unexpected_clause_value)
- << KindValue << getOpenMPClauseName(OMPC_defaultmap);
- } else if (isDefaultmapKind && !isDefaultmapModifier) {
- Diag(MLoc, diag::err_omp_unexpected_clause_value)
- << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
+ if (!isDefaultmapKind && isDefaultmapModifier) {
+ Diag(KindLoc, diag::err_omp_unexpected_clause_value)
+ << KindValue << getOpenMPClauseName(OMPC_defaultmap);
+ } else if (isDefaultmapKind && !isDefaultmapModifier) {
+ Diag(MLoc, diag::err_omp_unexpected_clause_value)
+ << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
+ } else {
+ Diag(MLoc, diag::err_omp_unexpected_clause_value)
+ << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
+ Diag(KindLoc, diag::err_omp_unexpected_clause_value)
+ << KindValue << getOpenMPClauseName(OMPC_defaultmap);
+ }
} else {
- Diag(MLoc, diag::err_omp_unexpected_clause_value)
- << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
- Diag(KindLoc, diag::err_omp_unexpected_clause_value)
- << KindValue << getOpenMPClauseName(OMPC_defaultmap);
+ StringRef ModifierValue =
+ "'alloc', 'from', 'to', 'tofrom', "
+ "'firstprivate', 'none', 'default', 'present'";
+ if (!isDefaultmapKind && isDefaultmapModifier) {
+ Diag(KindLoc, diag::err_omp_unexpected_clause_value)
+ << KindValue << getOpenMPClauseName(OMPC_defaultmap);
+ } else if (isDefaultmapKind && !isDefaultmapModifier) {
+ Diag(MLoc, diag::err_omp_unexpected_clause_value)
+ << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
+ } else {
+ Diag(MLoc, diag::err_omp_unexpected_clause_value)
+ << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
+ Diag(KindLoc, diag::err_omp_unexpected_clause_value)
+ << KindValue << getOpenMPClauseName(OMPC_defaultmap);
+ }
}
return nullptr;
}
@@ -18377,14 +18743,14 @@ bool Sema::ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc) {
Diag(Loc, diag::err_omp_region_not_file_context);
return false;
}
- ++DeclareTargetNestingLevel;
+ DeclareTargetNesting.push_back(Loc);
return true;
}
void Sema::ActOnFinishOpenMPDeclareTargetDirective() {
- assert(DeclareTargetNestingLevel > 0 &&
+ assert(!DeclareTargetNesting.empty() &&
"Unexpected ActOnFinishOpenMPDeclareTargetDirective");
- --DeclareTargetNestingLevel;
+ DeclareTargetNesting.pop_back();
}
NamedDecl *
@@ -18437,19 +18803,25 @@ void Sema::ActOnOpenMPDeclareTargetName(
(ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
Diag(Loc, diag::warn_omp_declare_target_after_first_use);
+ auto *VD = cast<ValueDecl>(ND);
Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
- OMPDeclareTargetDeclAttr::getDeviceType(cast<ValueDecl>(ND));
- if (DevTy.hasValue() && *DevTy != DT) {
+ OMPDeclareTargetDeclAttr::getDeviceType(VD);
+ Optional<SourceLocation> AttrLoc = OMPDeclareTargetDeclAttr::getLocation(VD);
+ if (DevTy.hasValue() && *DevTy != DT &&
+ (DeclareTargetNesting.empty() ||
+ *AttrLoc != DeclareTargetNesting.back())) {
Diag(Loc, diag::err_omp_device_type_mismatch)
<< OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DT)
<< OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(*DevTy);
return;
}
Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
- OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(cast<ValueDecl>(ND));
- if (!Res) {
- auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(Context, MT, DT,
- SourceRange(Loc, Loc));
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
+ if (!Res || (!DeclareTargetNesting.empty() &&
+ *AttrLoc == DeclareTargetNesting.back())) {
+ auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
+ Context, MT, DT, DeclareTargetNesting.size() + 1,
+ SourceRange(Loc, Loc));
ND->addAttr(A);
if (ASTMutationListener *ML = Context.getASTMutationListener())
ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
@@ -18541,7 +18913,9 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
isa<FunctionTemplateDecl>(D)) {
auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
Context, OMPDeclareTargetDeclAttr::MT_To,
- OMPDeclareTargetDeclAttr::DT_Any, SourceRange(IdLoc, IdLoc));
+ OMPDeclareTargetDeclAttr::DT_Any, DeclareTargetNesting.size(),
+ SourceRange(DeclareTargetNesting.back(),
+ DeclareTargetNesting.back()));
D->addAttr(A);
if (ASTMutationListener *ML = Context.getASTMutationListener())
ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
@@ -18554,11 +18928,31 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D);
}
-OMPClause *Sema::ActOnOpenMPToClause(ArrayRef<Expr *> VarList,
- CXXScopeSpec &MapperIdScopeSpec,
- DeclarationNameInfo &MapperId,
- const OMPVarListLocTy &Locs,
- ArrayRef<Expr *> UnresolvedMappers) {
+OMPClause *Sema::ActOnOpenMPToClause(
+ ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
+ ArrayRef<SourceLocation> MotionModifiersLoc,
+ CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
+ SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
+ const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
+ OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
+ OMPC_MOTION_MODIFIER_unknown};
+ SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
+
+ // Process motion-modifiers, flag errors for duplicate modifiers.
+ unsigned Count = 0;
+ for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
+ if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
+ llvm::find(Modifiers, MotionModifiers[I]) != std::end(Modifiers)) {
+ Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
+ continue;
+ }
+ assert(Count < NumberOfOMPMotionModifiers &&
+ "Modifiers exceed the allowed number of motion modifiers");
+ Modifiers[Count] = MotionModifiers[I];
+ ModifiersLoc[Count] = MotionModifiersLoc[I];
+ ++Count;
+ }
+
MappableVarListInfo MVLI(VarList);
checkMappableExpressionList(*this, DSAStack, OMPC_to, MVLI, Locs.StartLoc,
MapperIdScopeSpec, MapperId, UnresolvedMappers);
@@ -18567,15 +18961,35 @@ OMPClause *Sema::ActOnOpenMPToClause(ArrayRef<Expr *> VarList,
return OMPToClause::Create(
Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
- MVLI.VarComponents, MVLI.UDMapperList,
+ MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
}
-OMPClause *Sema::ActOnOpenMPFromClause(ArrayRef<Expr *> VarList,
- CXXScopeSpec &MapperIdScopeSpec,
- DeclarationNameInfo &MapperId,
- const OMPVarListLocTy &Locs,
- ArrayRef<Expr *> UnresolvedMappers) {
+OMPClause *Sema::ActOnOpenMPFromClause(
+ ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
+ ArrayRef<SourceLocation> MotionModifiersLoc,
+ CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
+ SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
+ const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
+ OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
+ OMPC_MOTION_MODIFIER_unknown};
+ SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
+
+ // Process motion-modifiers, flag errors for duplicate modifiers.
+ unsigned Count = 0;
+ for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
+ if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
+ llvm::find(Modifiers, MotionModifiers[I]) != std::end(Modifiers)) {
+ Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
+ continue;
+ }
+ assert(Count < NumberOfOMPMotionModifiers &&
+ "Modifiers exceed the allowed number of motion modifiers");
+ Modifiers[Count] = MotionModifiers[I];
+ ModifiersLoc[Count] = MotionModifiersLoc[I];
+ ++Count;
+ }
+
MappableVarListInfo MVLI(VarList);
checkMappableExpressionList(*this, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
MapperIdScopeSpec, MapperId, UnresolvedMappers);
@@ -18584,7 +18998,7 @@ OMPClause *Sema::ActOnOpenMPFromClause(ArrayRef<Expr *> VarList,
return OMPFromClause::Create(
Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
- MVLI.VarComponents, MVLI.UDMapperList,
+ MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
}
@@ -18661,8 +19075,8 @@ OMPClause *Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
// only need a component.
MVLI.VarBaseDeclarations.push_back(D);
MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
- MVLI.VarComponents.back().push_back(
- OMPClauseMappableExprCommon::MappableComponent(SimpleRefExpr, D));
+ MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
+ /*IsNonContiguous=*/false);
}
if (MVLI.ProcessedVarList.empty())
@@ -18713,8 +19127,8 @@ OMPClause *Sema::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
if (VD && (isa<OMPArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
Component = DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
- MVLI.VarComponents.back().push_back(
- OMPClauseMappableExprCommon::MappableComponent(Component, D));
+ MVLI.VarComponents.back().emplace_back(Component, D,
+ /*IsNonContiguous=*/false);
}
if (MVLI.ProcessedVarList.empty())
@@ -18780,7 +19194,8 @@ OMPClause *Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
// Store the components in the stack so that they can be used to check
// against other clauses later on.
- OMPClauseMappableExprCommon::MappableComponent MC(SimpleRefExpr, D);
+ OMPClauseMappableExprCommon::MappableComponent MC(
+ SimpleRefExpr, D, /*IsNonContiguous=*/false);
DSAStack->addMappableExpressionComponents(
D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
@@ -19022,7 +19437,7 @@ OMPClause *Sema::ActOnOpenMPUsesAllocatorClause(
[](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
!findOMPAlloctraitT(*this, StartLoc, DSAStack))
return nullptr;
- llvm::SmallSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
+ llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
StringRef Allocator =
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 8635397f4806..7fe7466725fa 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -137,6 +137,7 @@ ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) {
ICR_Conversion,
ICR_Conversion,
ICR_Conversion,
+ ICR_Conversion,
ICR_OCL_Scalar_Widening,
ICR_Complex_Real_Conversion,
ICR_Conversion,
@@ -174,6 +175,7 @@ static const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
"Compatible-types conversion",
"Derived-to-base conversion",
"Vector conversion",
+ "SVE Vector conversion",
"Vector splat",
"Complex-real conversion",
"Block Pointer conversion",
@@ -346,7 +348,6 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
ToType->isRealFloatingType()) {
if (IgnoreFloatToIntegralConversion)
return NK_Not_Narrowing;
- llvm::APSInt IntConstantValue;
const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted);
assert(Initializer && "Unknown conversion expression");
@@ -354,19 +355,20 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
if (Initializer->isValueDependent())
return NK_Dependent_Narrowing;
- if (Initializer->isIntegerConstantExpr(IntConstantValue, Ctx)) {
+ if (Optional<llvm::APSInt> IntConstantValue =
+ Initializer->getIntegerConstantExpr(Ctx)) {
// Convert the integer to the floating type.
llvm::APFloat Result(Ctx.getFloatTypeSemantics(ToType));
- Result.convertFromAPInt(IntConstantValue, IntConstantValue.isSigned(),
+ Result.convertFromAPInt(*IntConstantValue, IntConstantValue->isSigned(),
llvm::APFloat::rmNearestTiesToEven);
// And back.
- llvm::APSInt ConvertedValue = IntConstantValue;
+ llvm::APSInt ConvertedValue = *IntConstantValue;
bool ignored;
Result.convertToInteger(ConvertedValue,
llvm::APFloat::rmTowardZero, &ignored);
// If the resulting value is different, this was a narrowing conversion.
- if (IntConstantValue != ConvertedValue) {
- ConstantValue = APValue(IntConstantValue);
+ if (*IntConstantValue != ConvertedValue) {
+ ConstantValue = APValue(*IntConstantValue);
ConstantType = Initializer->getType();
return NK_Constant_Narrowing;
}
@@ -430,17 +432,18 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
(FromWidth == ToWidth && FromSigned != ToSigned) ||
(FromSigned && !ToSigned)) {
// Not all values of FromType can be represented in ToType.
- llvm::APSInt InitializerValue;
const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted);
// If it's value-dependent, we can't tell whether it's narrowing.
if (Initializer->isValueDependent())
return NK_Dependent_Narrowing;
- if (!Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) {
+ Optional<llvm::APSInt> OptInitializerValue;
+ if (!(OptInitializerValue = Initializer->getIntegerConstantExpr(Ctx))) {
// Such conversions on variables are always narrowing.
return NK_Variable_Narrowing;
}
+ llvm::APSInt &InitializerValue = *OptInitializerValue;
bool Narrowing = false;
if (FromWidth < ToWidth) {
// Negative -> unsigned is narrowing. Otherwise, more bits is never
@@ -1491,17 +1494,9 @@ Sema::TryImplicitConversion(Expr *From, QualType ToType,
/// converted expression. Flavor is the kind of conversion we're
/// performing, used in the error message. If @p AllowExplicit,
/// explicit user-defined conversions are permitted.
-ExprResult
-Sema::PerformImplicitConversion(Expr *From, QualType ToType,
- AssignmentAction Action, bool AllowExplicit) {
- ImplicitConversionSequence ICS;
- return PerformImplicitConversion(From, ToType, Action, AllowExplicit, ICS);
-}
-
-ExprResult
-Sema::PerformImplicitConversion(Expr *From, QualType ToType,
- AssignmentAction Action, bool AllowExplicit,
- ImplicitConversionSequence& ICS) {
+ExprResult Sema::PerformImplicitConversion(Expr *From, QualType ToType,
+ AssignmentAction Action,
+ bool AllowExplicit) {
if (checkPlaceholderForOverload(*this, From))
return ExprError();
@@ -1512,13 +1507,13 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
if (getLangOpts().ObjC)
CheckObjCBridgeRelatedConversions(From->getBeginLoc(), ToType,
From->getType(), From);
- ICS = ::TryImplicitConversion(*this, From, ToType,
- /*SuppressUserConversions=*/false,
- AllowExplicit ? AllowedExplicit::All
- : AllowedExplicit::None,
- /*InOverloadResolution=*/false,
- /*CStyle=*/false, AllowObjCWritebackConversion,
- /*AllowObjCConversionOnExplicit=*/false);
+ ImplicitConversionSequence ICS = ::TryImplicitConversion(
+ *this, From, ToType,
+ /*SuppressUserConversions=*/false,
+ AllowExplicit ? AllowedExplicit::All : AllowedExplicit::None,
+ /*InOverloadResolution=*/false,
+ /*CStyle=*/false, AllowObjCWritebackConversion,
+ /*AllowObjCConversionOnExplicit=*/false);
return PerformImplicitConversion(From, ToType, ICS, Action);
}
@@ -1649,6 +1644,13 @@ static bool IsVectorConversion(Sema &S, QualType FromType,
}
}
+ if (ToType->isSizelessBuiltinType() || FromType->isSizelessBuiltinType())
+ if (S.Context.areCompatibleSveTypes(FromType, ToType) ||
+ S.Context.areLaxCompatibleSveTypes(FromType, ToType)) {
+ ICK = ICK_SVE_Vector_Conversion;
+ return true;
+ }
+
// We can perform the conversion between vector types in the following cases:
// 1)vector types are equivalent AltiVec and GCC vector types
// 2)lax vector conversions are permitted and the vector types are of the
@@ -2183,21 +2185,22 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
// compatibility.
if (From) {
if (FieldDecl *MemberDecl = From->getSourceBitField()) {
- llvm::APSInt BitWidth;
+ Optional<llvm::APSInt> BitWidth;
if (FromType->isIntegralType(Context) &&
- MemberDecl->getBitWidth()->isIntegerConstantExpr(BitWidth, Context)) {
- llvm::APSInt ToSize(BitWidth.getBitWidth(), BitWidth.isUnsigned());
+ (BitWidth =
+ MemberDecl->getBitWidth()->getIntegerConstantExpr(Context))) {
+ llvm::APSInt ToSize(BitWidth->getBitWidth(), BitWidth->isUnsigned());
ToSize = Context.getTypeSize(ToType);
// Are we promoting to an int from a bitfield that fits in an int?
- if (BitWidth < ToSize ||
- (FromType->isSignedIntegerType() && BitWidth <= ToSize)) {
+ if (*BitWidth < ToSize ||
+ (FromType->isSignedIntegerType() && *BitWidth <= ToSize)) {
return To->getKind() == BuiltinType::Int;
}
// Are we promoting to an unsigned int from an unsigned bitfield
// that fits into an unsigned int?
- if (FromType->isUnsignedIntegerType() && BitWidth <= ToSize) {
+ if (FromType->isUnsignedIntegerType() && *BitWidth <= ToSize) {
return To->getKind() == BuiltinType::UInt;
}
@@ -3643,13 +3646,32 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
return true;
}
+// Helper for compareConversionFunctions that gets the FunctionType that the
+// conversion-operator return value 'points' to, or nullptr.
+static const FunctionType *
+getConversionOpReturnTyAsFunction(CXXConversionDecl *Conv) {
+ const FunctionType *ConvFuncTy = Conv->getType()->castAs<FunctionType>();
+ const PointerType *RetPtrTy =
+ ConvFuncTy->getReturnType()->getAs<PointerType>();
+
+ if (!RetPtrTy)
+ return nullptr;
+
+ return RetPtrTy->getPointeeType()->getAs<FunctionType>();
+}
+
/// Compare the user-defined conversion functions or constructors
/// of two user-defined conversion sequences to determine whether any ordering
/// is possible.
static ImplicitConversionSequence::CompareKind
compareConversionFunctions(Sema &S, FunctionDecl *Function1,
FunctionDecl *Function2) {
- if (!S.getLangOpts().ObjC || !S.getLangOpts().CPlusPlus11)
+ CXXConversionDecl *Conv1 = dyn_cast_or_null<CXXConversionDecl>(Function1);
+ CXXConversionDecl *Conv2 = dyn_cast_or_null<CXXConversionDecl>(Function2);
+ if (!Conv1 || !Conv2)
+ return ImplicitConversionSequence::Indistinguishable;
+
+ if (!Conv1->getParent()->isLambda() || !Conv2->getParent()->isLambda())
return ImplicitConversionSequence::Indistinguishable;
// Objective-C++:
@@ -3658,15 +3680,7 @@ compareConversionFunctions(Sema &S, FunctionDecl *Function1,
// respectively, always prefer the conversion to a function pointer,
// because the function pointer is more lightweight and is more likely
// to keep code working.
- CXXConversionDecl *Conv1 = dyn_cast_or_null<CXXConversionDecl>(Function1);
- if (!Conv1)
- return ImplicitConversionSequence::Indistinguishable;
-
- CXXConversionDecl *Conv2 = dyn_cast<CXXConversionDecl>(Function2);
- if (!Conv2)
- return ImplicitConversionSequence::Indistinguishable;
-
- if (Conv1->getParent()->isLambda() && Conv2->getParent()->isLambda()) {
+ if (S.getLangOpts().ObjC && S.getLangOpts().CPlusPlus11) {
bool Block1 = Conv1->getConversionType()->isBlockPointerType();
bool Block2 = Conv2->getConversionType()->isBlockPointerType();
if (Block1 != Block2)
@@ -3674,6 +3688,39 @@ compareConversionFunctions(Sema &S, FunctionDecl *Function1,
: ImplicitConversionSequence::Better;
}
+ // In order to support multiple calling conventions for the lambda conversion
+ // operator (such as when the free and member function calling convention is
+ // different), prefer the 'free' mechanism, followed by the calling-convention
+ // of operator(). The latter is in place to support the MSVC-like solution of
+ // defining ALL of the possible conversions in regards to calling-convention.
+ const FunctionType *Conv1FuncRet = getConversionOpReturnTyAsFunction(Conv1);
+ const FunctionType *Conv2FuncRet = getConversionOpReturnTyAsFunction(Conv2);
+
+ if (Conv1FuncRet && Conv2FuncRet &&
+ Conv1FuncRet->getCallConv() != Conv2FuncRet->getCallConv()) {
+ CallingConv Conv1CC = Conv1FuncRet->getCallConv();
+ CallingConv Conv2CC = Conv2FuncRet->getCallConv();
+
+ CXXMethodDecl *CallOp = Conv2->getParent()->getLambdaCallOperator();
+ const FunctionProtoType *CallOpProto =
+ CallOp->getType()->getAs<FunctionProtoType>();
+
+ CallingConv CallOpCC =
+ CallOp->getType()->getAs<FunctionType>()->getCallConv();
+ CallingConv DefaultFree = S.Context.getDefaultCallingConvention(
+ CallOpProto->isVariadic(), /*IsCXXMethod=*/false);
+ CallingConv DefaultMember = S.Context.getDefaultCallingConvention(
+ CallOpProto->isVariadic(), /*IsCXXMethod=*/true);
+
+ CallingConv PrefOrder[] = {DefaultFree, DefaultMember, CallOpCC};
+ for (CallingConv CC : PrefOrder) {
+ if (Conv1CC == CC)
+ return ImplicitConversionSequence::Better;
+ if (Conv2CC == CC)
+ return ImplicitConversionSequence::Worse;
+ }
+ }
+
return ImplicitConversionSequence::Indistinguishable;
}
@@ -4102,6 +4149,20 @@ CompareStandardConversionSequences(Sema &S, SourceLocation Loc,
: ImplicitConversionSequence::Worse;
}
+ if (SCS1.Second == ICK_SVE_Vector_Conversion &&
+ SCS2.Second == ICK_SVE_Vector_Conversion) {
+ bool SCS1IsCompatibleSVEVectorConversion =
+ S.Context.areCompatibleSveTypes(SCS1.getFromType(), SCS1.getToType(2));
+ bool SCS2IsCompatibleSVEVectorConversion =
+ S.Context.areCompatibleSveTypes(SCS2.getFromType(), SCS2.getToType(2));
+
+ if (SCS1IsCompatibleSVEVectorConversion !=
+ SCS2IsCompatibleSVEVectorConversion)
+ return SCS1IsCompatibleSVEVectorConversion
+ ? ImplicitConversionSequence::Better
+ : ImplicitConversionSequence::Worse;
+ }
+
return ImplicitConversionSequence::Indistinguishable;
}
@@ -4772,8 +4833,11 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// -- Otherwise, the reference shall be an lvalue reference to a
// non-volatile const type (i.e., cv1 shall be const), or the reference
// shall be an rvalue reference.
- if (!isRValRef && (!T1.isConstQualified() || T1.isVolatileQualified()))
+ if (!isRValRef && (!T1.isConstQualified() || T1.isVolatileQualified())) {
+ if (InitCategory.isRValue() && RefRelationship != Sema::Ref_Incompatible)
+ ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init, DeclType);
return ICS;
+ }
// -- If the initializer expression
//
@@ -4863,9 +4927,11 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// If T1 is reference-related to T2 and the reference is an rvalue
// reference, the initializer expression shall not be an lvalue.
- if (RefRelationship >= Sema::Ref_Related &&
- isRValRef && Init->Classify(S.Context).isLValue())
+ if (RefRelationship >= Sema::Ref_Related && isRValRef &&
+ Init->Classify(S.Context).isLValue()) {
+ ICS.setBad(BadConversionSequence::rvalue_ref_to_lvalue, Init, DeclType);
return ICS;
+ }
// C++ [over.ics.ref]p2:
// When a parameter of reference type is not bound directly to
@@ -4903,11 +4969,8 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// binding an rvalue reference to an lvalue other than a function
// lvalue.
// Note that the function case is not possible here.
- if (DeclType->isRValueReferenceType() && LValRefType) {
- // FIXME: This is the wrong BadConversionSequence. The problem is binding
- // an rvalue reference to a (non-function) lvalue, not binding an lvalue
- // reference to an rvalue!
- ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init, DeclType);
+ if (isRValRef && LValRefType) {
+ ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType);
return ICS;
}
@@ -4968,18 +5031,19 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
InOverloadResolution,
AllowObjCWritebackConversion);
}
- // FIXME: Check the other conditions here: array of character type,
- // initializer is a string literal.
- if (ToType->isArrayType()) {
- InitializedEntity Entity =
- InitializedEntity::InitializeParameter(S.Context, ToType,
- /*Consumed=*/false);
- if (S.CanPerformCopyInitialization(Entity, From)) {
- Result.setStandard();
- Result.Standard.setAsIdentityConversion();
- Result.Standard.setFromType(ToType);
- Result.Standard.setAllToTypes(ToType);
- return Result;
+
+ if (const auto *AT = S.Context.getAsArrayType(ToType)) {
+ if (S.IsStringInit(From->getInit(0), AT)) {
+ InitializedEntity Entity =
+ InitializedEntity::InitializeParameter(S.Context, ToType,
+ /*Consumed=*/false);
+ if (S.CanPerformCopyInitialization(Entity, From)) {
+ Result.setStandard();
+ Result.Standard.setAsIdentityConversion();
+ Result.Standard.setFromType(ToType);
+ Result.Standard.setAllToTypes(ToType);
+ return Result;
+ }
}
}
}
@@ -5491,7 +5555,6 @@ static bool CheckConvertedConstantConversions(Sema &S,
// conversions are fine.
switch (SCS.Second) {
case ICK_Identity:
- case ICK_Function_Conversion:
case ICK_Integral_Promotion:
case ICK_Integral_Conversion: // Narrowing conversions are checked elsewhere.
case ICK_Zero_Queue_Conversion:
@@ -5522,6 +5585,7 @@ static bool CheckConvertedConstantConversions(Sema &S,
case ICK_Compatible_Conversion:
case ICK_Derived_To_Base:
case ICK_Vector_Conversion:
+ case ICK_SVE_Vector_Conversion:
case ICK_Vector_Splat:
case ICK_Complex_Real:
case ICK_Block_Pointer_Conversion:
@@ -5537,6 +5601,7 @@ static bool CheckConvertedConstantConversions(Sema &S,
case ICK_Function_To_Pointer:
llvm_unreachable("found a first conversion kind in Second");
+ case ICK_Function_Conversion:
case ICK_Qualification:
llvm_unreachable("found a third conversion kind in Second");
@@ -5553,7 +5618,8 @@ static bool CheckConvertedConstantConversions(Sema &S,
static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
QualType T, APValue &Value,
Sema::CCEKind CCE,
- bool RequireInt) {
+ bool RequireInt,
+ NamedDecl *Dest) {
assert(S.getLangOpts().CPlusPlus11 &&
"converted constant expression outside C++11");
@@ -5583,9 +5649,10 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
SCS = &ICS.Standard;
break;
case ImplicitConversionSequence::UserDefinedConversion:
- // We are converting to a non-class type, so the Before sequence
- // must be trivial.
- SCS = &ICS.UserDefined.After;
+ if (T->isRecordType())
+ SCS = &ICS.UserDefined.Before;
+ else
+ SCS = &ICS.UserDefined.After;
break;
case ImplicitConversionSequence::AmbiguousConversion:
case ImplicitConversionSequence::BadConversion:
@@ -5612,8 +5679,20 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
<< From->getType() << From->getSourceRange() << T;
}
- ExprResult Result =
- S.PerformImplicitConversion(From, T, ICS, Sema::AA_Converting);
+ // Usually we can simply apply the ImplicitConversionSequence we formed
+ // earlier, but that's not guaranteed to work when initializing an object of
+ // class type.
+ ExprResult Result;
+ if (T->isRecordType()) {
+ assert(CCE == Sema::CCEK_TemplateArg &&
+ "unexpected class type converted constant expr");
+ Result = S.PerformCopyInitialization(
+ InitializedEntity::InitializeTemplateParameter(
+ T, cast<NonTypeTemplateParmDecl>(Dest)),
+ SourceLocation(), From);
+ } else {
+ Result = S.PerformImplicitConversion(From, T, ICS, Sema::AA_Converting);
+ }
if (Result.isInvalid())
return Result;
@@ -5626,6 +5705,7 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
return Result;
// Check for a narrowing implicit conversion.
+ bool ReturnPreNarrowingValue = false;
APValue PreNarrowingValue;
QualType PreNarrowingType;
switch (SCS->getNarrowingKind(S.Context, Result.get(), PreNarrowingValue,
@@ -5640,12 +5720,22 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
break;
case NK_Constant_Narrowing:
+ if (CCE == Sema::CCEK_ArrayBound &&
+ PreNarrowingType->isIntegralOrEnumerationType() &&
+ PreNarrowingValue.isInt()) {
+ // Don't diagnose array bound narrowing here; we produce more precise
+ // errors by allowing the un-narrowed value through.
+ ReturnPreNarrowingValue = true;
+ break;
+ }
S.Diag(From->getBeginLoc(), diag::ext_cce_narrowing)
<< CCE << /*Constant*/ 1
<< PreNarrowingValue.getAsString(S.Context, PreNarrowingType) << T;
break;
case NK_Type_Narrowing:
+ // FIXME: It would be better to diagnose that the expression is not a
+ // constant expression.
S.Diag(From->getBeginLoc(), diag::ext_cce_narrowing)
<< CCE << /*Constant*/ 0 << From->getType() << T;
break;
@@ -5660,11 +5750,16 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
SmallVector<PartialDiagnosticAt, 8> Notes;
Expr::EvalResult Eval;
Eval.Diag = &Notes;
- Expr::ConstExprUsage Usage = CCE == Sema::CCEK_TemplateArg
- ? Expr::EvaluateForMangling
- : Expr::EvaluateForCodeGen;
- if (!Result.get()->EvaluateAsConstantExpr(Eval, Usage, S.Context) ||
+ ConstantExprKind Kind;
+ if (CCE == Sema::CCEK_TemplateArg && T->isRecordType())
+ Kind = ConstantExprKind::ClassTemplateArgument;
+ else if (CCE == Sema::CCEK_TemplateArg)
+ Kind = ConstantExprKind::NonClassTemplateArgument;
+ else
+ Kind = ConstantExprKind::Normal;
+
+ if (!Result.get()->EvaluateAsConstantExpr(Eval, S.Context, Kind) ||
(RequireInt && !Eval.Val.isInt())) {
// The expression can't be folded, so we can't keep it at this position in
// the AST.
@@ -5674,15 +5769,23 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
if (Notes.empty()) {
// It's a constant expression.
- return ConstantExpr::Create(S.Context, Result.get(), Value);
+ Expr *E = ConstantExpr::Create(S.Context, Result.get(), Value);
+ if (ReturnPreNarrowingValue)
+ Value = std::move(PreNarrowingValue);
+ return E;
}
}
// 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)
+ Notes[0].second.getDiagID() == diag::note_invalid_subexpr_in_const_expr) {
S.Diag(Notes[0].first, diag::err_expr_not_cce) << CCE;
- else {
+ } else if (!Notes.empty() && Notes[0].second.getDiagID() ==
+ diag::note_constexpr_invalid_template_arg) {
+ Notes[0].second.setDiagID(diag::err_constexpr_invalid_template_arg);
+ for (unsigned I = 0; I < Notes.size(); ++I)
+ S.Diag(Notes[I].first, Notes[I].second);
+ } else {
S.Diag(From->getBeginLoc(), diag::err_expr_not_cce)
<< CCE << From->getSourceRange();
for (unsigned I = 0; I < Notes.size(); ++I)
@@ -5692,8 +5795,10 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
}
ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
- APValue &Value, CCEKind CCE) {
- return ::CheckConvertedConstantExpression(*this, From, T, Value, CCE, false);
+ APValue &Value, CCEKind CCE,
+ NamedDecl *Dest) {
+ return ::CheckConvertedConstantExpression(*this, From, T, Value, CCE, false,
+ Dest);
}
ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
@@ -5702,7 +5807,8 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
assert(T->isIntegralOrEnumerationType() && "unexpected converted const type");
APValue V;
- auto R = ::CheckConvertedConstantExpression(*this, From, T, V, CCE, true);
+ auto R = ::CheckConvertedConstantExpression(*this, From, T, V, CCE, true,
+ /*Dest=*/nullptr);
if (!R.isInvalid() && !R.get()->isValueDependent())
Value = V.getInt();
return R;
@@ -5831,7 +5937,8 @@ diagnoseNoViableConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From,
// Record usage of conversion in an implicit cast.
From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(),
CK_UserDefinedConversion, Result.get(),
- nullptr, Result.get()->getValueKind());
+ nullptr, Result.get()->getValueKind(),
+ SemaRef.CurFPFeatureOverrides());
}
return false;
}
@@ -5860,7 +5967,8 @@ static bool recordConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From,
// Record usage of conversion in an implicit cast.
From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(),
CK_UserDefinedConversion, Result.get(),
- nullptr, Result.get()->getValueKind());
+ nullptr, Result.get()->getValueKind(),
+ SemaRef.CurFPFeatureOverrides());
return false;
}
@@ -7265,8 +7373,8 @@ void Sema::AddConversionCandidate(
VK_LValue, From->getBeginLoc());
ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack,
Context.getPointerType(Conversion->getType()),
- CK_FunctionToPointerDecay,
- &ConversionRef, VK_RValue);
+ CK_FunctionToPointerDecay, &ConversionRef,
+ VK_RValue, FPOptionsOverride());
QualType ConversionType = Conversion->getConversionType();
if (!isCompleteType(From->getBeginLoc(), ConversionType)) {
@@ -7735,26 +7843,14 @@ public:
bool AllowExplicitConversions,
const Qualifiers &VisibleTypeConversionsQuals);
- /// pointer_begin - First pointer type found;
- iterator pointer_begin() { return PointerTypes.begin(); }
-
- /// pointer_end - Past the last pointer type found;
- iterator pointer_end() { return PointerTypes.end(); }
-
- /// member_pointer_begin - First member pointer type found;
- iterator member_pointer_begin() { return MemberPointerTypes.begin(); }
-
- /// member_pointer_end - Past the last member pointer type found;
- iterator member_pointer_end() { return MemberPointerTypes.end(); }
-
- /// enumeration_begin - First enumeration type found;
- iterator enumeration_begin() { return EnumerationTypes.begin(); }
-
- /// enumeration_end - Past the last enumeration type found;
- iterator enumeration_end() { return EnumerationTypes.end(); }
-
+ llvm::iterator_range<iterator> pointer_types() { return PointerTypes; }
+ llvm::iterator_range<iterator> member_pointer_types() {
+ return MemberPointerTypes;
+ }
+ llvm::iterator_range<iterator> enumeration_types() {
+ return EnumerationTypes;
+ }
llvm::iterator_range<iterator> vector_types() { return VectorTypes; }
-
llvm::iterator_range<iterator> matrix_types() { return MatrixTypes; }
bool containsMatrixType(QualType Ty) const { return MatrixTypes.count(Ty); }
@@ -8091,12 +8187,16 @@ class BuiltinOperatorOverloadBuilder {
ArithmeticTypes.push_back(S.Context.IntTy);
ArithmeticTypes.push_back(S.Context.LongTy);
ArithmeticTypes.push_back(S.Context.LongLongTy);
- if (S.Context.getTargetInfo().hasInt128Type())
+ if (S.Context.getTargetInfo().hasInt128Type() ||
+ (S.Context.getAuxTargetInfo() &&
+ S.Context.getAuxTargetInfo()->hasInt128Type()))
ArithmeticTypes.push_back(S.Context.Int128Ty);
ArithmeticTypes.push_back(S.Context.UnsignedIntTy);
ArithmeticTypes.push_back(S.Context.UnsignedLongTy);
ArithmeticTypes.push_back(S.Context.UnsignedLongLongTy);
- if (S.Context.getTargetInfo().hasInt128Type())
+ if (S.Context.getTargetInfo().hasInt128Type() ||
+ (S.Context.getAuxTargetInfo() &&
+ S.Context.getAuxTargetInfo()->hasInt128Type()))
ArithmeticTypes.push_back(S.Context.UnsignedInt128Ty);
LastPromotedIntegralType = ArithmeticTypes.size();
LastPromotedArithmeticType = ArithmeticTypes.size();
@@ -8238,19 +8338,17 @@ public:
// T* operator++(T*VQ&, int);
// T* operator--(T*VQ&, int);
void addPlusPlusMinusMinusPointerOverloads() {
- for (BuiltinCandidateTypeSet::iterator
- Ptr = CandidateTypes[0].pointer_begin(),
- PtrEnd = CandidateTypes[0].pointer_end();
- Ptr != PtrEnd; ++Ptr) {
+ for (QualType PtrTy : CandidateTypes[0].pointer_types()) {
// Skip pointer types that aren't pointers to object types.
- if (!(*Ptr)->getPointeeType()->isObjectType())
+ if (!PtrTy->getPointeeType()->isObjectType())
continue;
- addPlusPlusMinusMinusStyleOverloads(*Ptr,
- (!(*Ptr).isVolatileQualified() &&
- VisibleTypeConversionsQuals.hasVolatile()),
- (!(*Ptr).isRestrictQualified() &&
- VisibleTypeConversionsQuals.hasRestrict()));
+ addPlusPlusMinusMinusStyleOverloads(
+ PtrTy,
+ (!PtrTy.isVolatileQualified() &&
+ VisibleTypeConversionsQuals.hasVolatile()),
+ (!PtrTy.isRestrictQualified() &&
+ VisibleTypeConversionsQuals.hasRestrict()));
}
}
@@ -8265,11 +8363,7 @@ public:
// ref-qualifier, there exist candidate operator functions of the form
// T& operator*(T*);
void addUnaryStarPointerOverloads() {
- for (BuiltinCandidateTypeSet::iterator
- Ptr = CandidateTypes[0].pointer_begin(),
- PtrEnd = CandidateTypes[0].pointer_end();
- Ptr != PtrEnd; ++Ptr) {
- QualType ParamTy = *Ptr;
+ for (QualType ParamTy : CandidateTypes[0].pointer_types()) {
QualType PointeeTy = ParamTy->getPointeeType();
if (!PointeeTy->isObjectType() && !PointeeTy->isFunctionType())
continue;
@@ -8309,13 +8403,8 @@ public:
//
// T* operator+(T*);
void addUnaryPlusPointerOverloads() {
- for (BuiltinCandidateTypeSet::iterator
- Ptr = CandidateTypes[0].pointer_begin(),
- PtrEnd = CandidateTypes[0].pointer_end();
- Ptr != PtrEnd; ++Ptr) {
- QualType ParamTy = *Ptr;
+ for (QualType ParamTy : CandidateTypes[0].pointer_types())
S.AddBuiltinCandidate(&ParamTy, Args, CandidateSet);
- }
}
// C++ [over.built]p10:
@@ -8349,16 +8438,12 @@ public:
llvm::SmallPtrSet<QualType, 8> AddedTypes;
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
- for (BuiltinCandidateTypeSet::iterator
- MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
- MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
- MemPtr != MemPtrEnd;
- ++MemPtr) {
+ for (QualType MemPtrTy : CandidateTypes[ArgIdx].member_pointer_types()) {
// Don't add the same builtin candidate twice.
- if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)).second)
+ if (!AddedTypes.insert(S.Context.getCanonicalType(MemPtrTy)).second)
continue;
- QualType ParamTypes[2] = { *MemPtr, *MemPtr };
+ QualType ParamTypes[2] = {MemPtrTy, MemPtrTy};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
@@ -8401,8 +8486,7 @@ public:
UserDefinedBinaryOperators;
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
- if (CandidateTypes[ArgIdx].enumeration_begin() !=
- CandidateTypes[ArgIdx].enumeration_end()) {
+ if (!CandidateTypes[ArgIdx].enumeration_types().empty()) {
for (OverloadCandidateSet::iterator C = CandidateSet.begin(),
CEnd = CandidateSet.end();
C != CEnd; ++C) {
@@ -8440,22 +8524,16 @@ public:
llvm::SmallPtrSet<QualType, 8> AddedTypes;
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
- for (BuiltinCandidateTypeSet::iterator
- Ptr = CandidateTypes[ArgIdx].pointer_begin(),
- PtrEnd = CandidateTypes[ArgIdx].pointer_end();
- Ptr != PtrEnd; ++Ptr) {
+ for (QualType PtrTy : CandidateTypes[ArgIdx].pointer_types()) {
// Don't add the same builtin candidate twice.
- if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)).second)
+ if (!AddedTypes.insert(S.Context.getCanonicalType(PtrTy)).second)
continue;
- QualType ParamTypes[2] = { *Ptr, *Ptr };
+ QualType ParamTypes[2] = {PtrTy, PtrTy};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
- for (BuiltinCandidateTypeSet::iterator
- Enum = CandidateTypes[ArgIdx].enumeration_begin(),
- EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
- Enum != EnumEnd; ++Enum) {
- CanQualType CanonType = S.Context.getCanonicalType(*Enum);
+ for (QualType EnumTy : CandidateTypes[ArgIdx].enumeration_types()) {
+ CanQualType CanonType = S.Context.getCanonicalType(EnumTy);
// Don't add the same builtin candidate twice, or if a user defined
// candidate exists.
@@ -8463,7 +8541,7 @@ public:
UserDefinedBinaryOperators.count(std::make_pair(CanonType,
CanonType)))
continue;
- QualType ParamTypes[2] = { *Enum, *Enum };
+ QualType ParamTypes[2] = {EnumTy, EnumTy};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
}
@@ -8495,15 +8573,12 @@ public:
S.Context.getPointerDiffType(),
S.Context.getPointerDiffType(),
};
- for (BuiltinCandidateTypeSet::iterator
- Ptr = CandidateTypes[Arg].pointer_begin(),
- PtrEnd = CandidateTypes[Arg].pointer_end();
- Ptr != PtrEnd; ++Ptr) {
- QualType PointeeTy = (*Ptr)->getPointeeType();
+ for (QualType PtrTy : CandidateTypes[Arg].pointer_types()) {
+ QualType PointeeTy = PtrTy->getPointeeType();
if (!PointeeTy->isObjectType())
continue;
- AsymmetricParamTypes[Arg] = *Ptr;
+ AsymmetricParamTypes[Arg] = PtrTy;
if (Arg == 0 || Op == OO_Plus) {
// operator+(T*, ptrdiff_t) or operator-(T*, ptrdiff_t)
// T* operator+(ptrdiff_t, T*);
@@ -8511,10 +8586,10 @@ public:
}
if (Op == OO_Minus) {
// ptrdiff_t operator-(T, T);
- if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)).second)
+ if (!AddedTypes.insert(S.Context.getCanonicalType(PtrTy)).second)
continue;
- QualType ParamTypes[2] = { *Ptr, *Ptr };
+ QualType ParamTypes[2] = {PtrTy, PtrTy};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
}
@@ -8670,24 +8745,18 @@ public:
llvm::SmallPtrSet<QualType, 8> AddedTypes;
for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) {
- for (BuiltinCandidateTypeSet::iterator
- Enum = CandidateTypes[ArgIdx].enumeration_begin(),
- EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
- Enum != EnumEnd; ++Enum) {
- if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum)).second)
+ for (QualType EnumTy : CandidateTypes[ArgIdx].enumeration_types()) {
+ if (!AddedTypes.insert(S.Context.getCanonicalType(EnumTy)).second)
continue;
- AddBuiltinAssignmentOperatorCandidates(S, *Enum, Args, CandidateSet);
+ AddBuiltinAssignmentOperatorCandidates(S, EnumTy, Args, CandidateSet);
}
- for (BuiltinCandidateTypeSet::iterator
- MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
- MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
- MemPtr != MemPtrEnd; ++MemPtr) {
- if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)).second)
+ for (QualType MemPtrTy : CandidateTypes[ArgIdx].member_pointer_types()) {
+ if (!AddedTypes.insert(S.Context.getCanonicalType(MemPtrTy)).second)
continue;
- AddBuiltinAssignmentOperatorCandidates(S, *MemPtr, Args, CandidateSet);
+ AddBuiltinAssignmentOperatorCandidates(S, MemPtrTy, Args, CandidateSet);
}
}
}
@@ -8712,49 +8781,44 @@ public:
/// Set of (canonical) types that we've already handled.
llvm::SmallPtrSet<QualType, 8> AddedTypes;
- for (BuiltinCandidateTypeSet::iterator
- Ptr = CandidateTypes[0].pointer_begin(),
- PtrEnd = CandidateTypes[0].pointer_end();
- Ptr != PtrEnd; ++Ptr) {
+ for (QualType PtrTy : CandidateTypes[0].pointer_types()) {
// If this is operator=, keep track of the builtin candidates we added.
if (isEqualOp)
- AddedTypes.insert(S.Context.getCanonicalType(*Ptr));
- else if (!(*Ptr)->getPointeeType()->isObjectType())
+ AddedTypes.insert(S.Context.getCanonicalType(PtrTy));
+ else if (!PtrTy->getPointeeType()->isObjectType())
continue;
// non-volatile version
QualType ParamTypes[2] = {
- S.Context.getLValueReferenceType(*Ptr),
- isEqualOp ? *Ptr : S.Context.getPointerDiffType(),
+ S.Context.getLValueReferenceType(PtrTy),
+ isEqualOp ? PtrTy : S.Context.getPointerDiffType(),
};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
/*IsAssignmentOperator=*/ isEqualOp);
- bool NeedVolatile = !(*Ptr).isVolatileQualified() &&
+ bool NeedVolatile = !PtrTy.isVolatileQualified() &&
VisibleTypeConversionsQuals.hasVolatile();
if (NeedVolatile) {
// volatile version
ParamTypes[0] =
- S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr));
+ S.Context.getLValueReferenceType(S.Context.getVolatileType(PtrTy));
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
/*IsAssignmentOperator=*/isEqualOp);
}
- if (!(*Ptr).isRestrictQualified() &&
+ if (!PtrTy.isRestrictQualified() &&
VisibleTypeConversionsQuals.hasRestrict()) {
// restrict version
- ParamTypes[0]
- = S.Context.getLValueReferenceType(S.Context.getRestrictType(*Ptr));
+ ParamTypes[0] =
+ S.Context.getLValueReferenceType(S.Context.getRestrictType(PtrTy));
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
/*IsAssignmentOperator=*/isEqualOp);
if (NeedVolatile) {
// volatile restrict version
- ParamTypes[0]
- = S.Context.getLValueReferenceType(
- S.Context.getCVRQualifiedType(*Ptr,
- (Qualifiers::Volatile |
- Qualifiers::Restrict)));
+ ParamTypes[0] =
+ S.Context.getLValueReferenceType(S.Context.getCVRQualifiedType(
+ PtrTy, (Qualifiers::Volatile | Qualifiers::Restrict)));
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
/*IsAssignmentOperator=*/isEqualOp);
}
@@ -8762,48 +8826,43 @@ public:
}
if (isEqualOp) {
- for (BuiltinCandidateTypeSet::iterator
- Ptr = CandidateTypes[1].pointer_begin(),
- PtrEnd = CandidateTypes[1].pointer_end();
- Ptr != PtrEnd; ++Ptr) {
+ for (QualType PtrTy : CandidateTypes[1].pointer_types()) {
// Make sure we don't add the same candidate twice.
- if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)).second)
+ if (!AddedTypes.insert(S.Context.getCanonicalType(PtrTy)).second)
continue;
QualType ParamTypes[2] = {
- S.Context.getLValueReferenceType(*Ptr),
- *Ptr,
+ S.Context.getLValueReferenceType(PtrTy),
+ PtrTy,
};
// non-volatile version
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
/*IsAssignmentOperator=*/true);
- bool NeedVolatile = !(*Ptr).isVolatileQualified() &&
- VisibleTypeConversionsQuals.hasVolatile();
+ bool NeedVolatile = !PtrTy.isVolatileQualified() &&
+ VisibleTypeConversionsQuals.hasVolatile();
if (NeedVolatile) {
// volatile version
- ParamTypes[0] =
- S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr));
+ ParamTypes[0] = S.Context.getLValueReferenceType(
+ S.Context.getVolatileType(PtrTy));
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
/*IsAssignmentOperator=*/true);
}
- if (!(*Ptr).isRestrictQualified() &&
+ if (!PtrTy.isRestrictQualified() &&
VisibleTypeConversionsQuals.hasRestrict()) {
// restrict version
- ParamTypes[0]
- = S.Context.getLValueReferenceType(S.Context.getRestrictType(*Ptr));
+ ParamTypes[0] = S.Context.getLValueReferenceType(
+ S.Context.getRestrictType(PtrTy));
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
/*IsAssignmentOperator=*/true);
if (NeedVolatile) {
// volatile restrict version
- ParamTypes[0]
- = S.Context.getLValueReferenceType(
- S.Context.getCVRQualifiedType(*Ptr,
- (Qualifiers::Volatile |
- Qualifiers::Restrict)));
+ ParamTypes[0] =
+ S.Context.getLValueReferenceType(S.Context.getCVRQualifiedType(
+ PtrTy, (Qualifiers::Volatile | Qualifiers::Restrict)));
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
/*IsAssignmentOperator=*/true);
}
@@ -8938,12 +8997,9 @@ public:
// T* operator+(ptrdiff_t, T*); [ABOVE]
// T& operator[](ptrdiff_t, T*);
void addSubscriptOverloads() {
- for (BuiltinCandidateTypeSet::iterator
- Ptr = CandidateTypes[0].pointer_begin(),
- PtrEnd = CandidateTypes[0].pointer_end();
- Ptr != PtrEnd; ++Ptr) {
- QualType ParamTypes[2] = { *Ptr, S.Context.getPointerDiffType() };
- QualType PointeeType = (*Ptr)->getPointeeType();
+ for (QualType PtrTy : CandidateTypes[0].pointer_types()) {
+ QualType ParamTypes[2] = {PtrTy, S.Context.getPointerDiffType()};
+ QualType PointeeType = PtrTy->getPointeeType();
if (!PointeeType->isObjectType())
continue;
@@ -8951,12 +9007,9 @@ public:
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
- for (BuiltinCandidateTypeSet::iterator
- Ptr = CandidateTypes[1].pointer_begin(),
- PtrEnd = CandidateTypes[1].pointer_end();
- Ptr != PtrEnd; ++Ptr) {
- QualType ParamTypes[2] = { S.Context.getPointerDiffType(), *Ptr };
- QualType PointeeType = (*Ptr)->getPointeeType();
+ for (QualType PtrTy : CandidateTypes[1].pointer_types()) {
+ QualType ParamTypes[2] = {S.Context.getPointerDiffType(), PtrTy};
+ QualType PointeeType = PtrTy->getPointeeType();
if (!PointeeType->isObjectType())
continue;
@@ -8975,11 +9028,8 @@ public:
//
// where CV12 is the union of CV1 and CV2.
void addArrowStarOverloads() {
- for (BuiltinCandidateTypeSet::iterator
- Ptr = CandidateTypes[0].pointer_begin(),
- PtrEnd = CandidateTypes[0].pointer_end();
- Ptr != PtrEnd; ++Ptr) {
- QualType C1Ty = (*Ptr);
+ for (QualType PtrTy : CandidateTypes[0].pointer_types()) {
+ QualType C1Ty = PtrTy;
QualType C1;
QualifierCollector Q1;
C1 = QualType(Q1.strip(C1Ty->getPointeeType()), 0);
@@ -8992,16 +9042,13 @@ public:
continue;
if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict())
continue;
- for (BuiltinCandidateTypeSet::iterator
- MemPtr = CandidateTypes[1].member_pointer_begin(),
- MemPtrEnd = CandidateTypes[1].member_pointer_end();
- MemPtr != MemPtrEnd; ++MemPtr) {
- const MemberPointerType *mptr = cast<MemberPointerType>(*MemPtr);
+ for (QualType MemPtrTy : CandidateTypes[1].member_pointer_types()) {
+ const MemberPointerType *mptr = cast<MemberPointerType>(MemPtrTy);
QualType C2 = QualType(mptr->getClass(), 0);
C2 = C2.getUnqualifiedType();
if (C1 != C2 && !S.IsDerivedFrom(CandidateSet.getLocation(), C1, C2))
break;
- QualType ParamTypes[2] = { *Ptr, *MemPtr };
+ QualType ParamTypes[2] = {PtrTy, MemPtrTy};
// build CV12 T&
QualType T = mptr->getPointeeType();
if (!VisibleTypeConversionsQuals.hasVolatile() &&
@@ -9031,40 +9078,31 @@ public:
llvm::SmallPtrSet<QualType, 8> AddedTypes;
for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) {
- for (BuiltinCandidateTypeSet::iterator
- Ptr = CandidateTypes[ArgIdx].pointer_begin(),
- PtrEnd = CandidateTypes[ArgIdx].pointer_end();
- Ptr != PtrEnd; ++Ptr) {
- if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)).second)
+ for (QualType PtrTy : CandidateTypes[ArgIdx].pointer_types()) {
+ if (!AddedTypes.insert(S.Context.getCanonicalType(PtrTy)).second)
continue;
- QualType ParamTypes[2] = { *Ptr, *Ptr };
+ QualType ParamTypes[2] = {PtrTy, PtrTy};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
- for (BuiltinCandidateTypeSet::iterator
- MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
- MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
- MemPtr != MemPtrEnd; ++MemPtr) {
- if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)).second)
+ for (QualType MemPtrTy : CandidateTypes[ArgIdx].member_pointer_types()) {
+ if (!AddedTypes.insert(S.Context.getCanonicalType(MemPtrTy)).second)
continue;
- QualType ParamTypes[2] = { *MemPtr, *MemPtr };
+ QualType ParamTypes[2] = {MemPtrTy, MemPtrTy};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
if (S.getLangOpts().CPlusPlus11) {
- for (BuiltinCandidateTypeSet::iterator
- Enum = CandidateTypes[ArgIdx].enumeration_begin(),
- EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
- Enum != EnumEnd; ++Enum) {
- if (!(*Enum)->castAs<EnumType>()->getDecl()->isScoped())
+ for (QualType EnumTy : CandidateTypes[ArgIdx].enumeration_types()) {
+ if (!EnumTy->castAs<EnumType>()->getDecl()->isScoped())
continue;
- if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum)).second)
+ if (!AddedTypes.insert(S.Context.getCanonicalType(EnumTy)).second)
continue;
- QualType ParamTypes[2] = { *Enum, *Enum };
+ QualType ParamTypes[2] = {EnumTy, EnumTy};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
}
@@ -9508,6 +9546,75 @@ bool clang::isBetterOverloadCandidate(
else if (!Cand1.Viable)
return false;
+ // [CUDA] A function with 'never' preference is marked not viable, therefore
+ // is never shown up here. The worst preference shown up here is 'wrong side',
+ // e.g. an H function called by a HD function in device compilation. This is
+ // valid AST as long as the HD function is not emitted, e.g. it is an inline
+ // function which is called only by an H function. A deferred diagnostic will
+ // be triggered if it is emitted. However a wrong-sided function is still
+ // a viable candidate here.
+ //
+ // If Cand1 can be emitted and Cand2 cannot be emitted in the current
+ // context, Cand1 is better than Cand2. If Cand1 can not be emitted and Cand2
+ // can be emitted, Cand1 is not better than Cand2. This rule should have
+ // precedence over other rules.
+ //
+ // If both Cand1 and Cand2 can be emitted, or neither can be emitted, then
+ // other rules should be used to determine which is better. This is because
+ // host/device based overloading resolution is mostly for determining
+ // viability of a function. If two functions are both viable, other factors
+ // should take precedence in preference, e.g. the standard-defined preferences
+ // like argument conversion ranks or enable_if partial-ordering. The
+ // preference for pass-object-size parameters is probably most similar to a
+ // type-based-overloading decision and so should take priority.
+ //
+ // If other rules cannot determine which is better, CUDA preference will be
+ // used again to determine which is better.
+ //
+ // TODO: Currently IdentifyCUDAPreference does not return correct values
+ // for functions called in global variable initializers due to missing
+ // correct context about device/host. Therefore we can only enforce this
+ // rule when there is a caller. We should enforce this rule for functions
+ // in global variable initializers once proper context is added.
+ //
+ // TODO: We can only enable the hostness based overloading resolution when
+ // -fgpu-exclude-wrong-side-overloads is on since this requires deferring
+ // overloading resolution diagnostics.
+ if (S.getLangOpts().CUDA && Cand1.Function && Cand2.Function &&
+ S.getLangOpts().GPUExcludeWrongSideOverloads) {
+ if (FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext)) {
+ bool IsCallerImplicitHD = Sema::isCUDAImplicitHostDeviceFunction(Caller);
+ bool IsCand1ImplicitHD =
+ Sema::isCUDAImplicitHostDeviceFunction(Cand1.Function);
+ bool IsCand2ImplicitHD =
+ Sema::isCUDAImplicitHostDeviceFunction(Cand2.Function);
+ auto P1 = S.IdentifyCUDAPreference(Caller, Cand1.Function);
+ auto P2 = S.IdentifyCUDAPreference(Caller, Cand2.Function);
+ assert(P1 != Sema::CFP_Never && P2 != Sema::CFP_Never);
+ // The implicit HD function may be a function in a system header which
+ // is forced by pragma. In device compilation, if we prefer HD candidates
+ // over wrong-sided candidates, overloading resolution may change, which
+ // may result in non-deferrable diagnostics. As a workaround, we let
+ // implicit HD candidates take equal preference as wrong-sided candidates.
+ // This will preserve the overloading resolution.
+ // TODO: We still need special handling of implicit HD functions since
+ // they may incur other diagnostics to be deferred. We should make all
+ // host/device related diagnostics deferrable and remove special handling
+ // of implicit HD functions.
+ auto EmitThreshold =
+ (S.getLangOpts().CUDAIsDevice && IsCallerImplicitHD &&
+ (IsCand1ImplicitHD || IsCand2ImplicitHD))
+ ? Sema::CFP_Never
+ : Sema::CFP_WrongSide;
+ auto Cand1Emittable = P1 > EmitThreshold;
+ auto Cand2Emittable = P2 > EmitThreshold;
+ if (Cand1Emittable && !Cand2Emittable)
+ return true;
+ if (!Cand1Emittable && Cand2Emittable)
+ return false;
+ }
+ }
+
// C++ [over.match.best]p1:
//
// -- if F is a static member function, ICS1(F) is defined such
@@ -9742,12 +9849,6 @@ bool clang::isBetterOverloadCandidate(
return Cmp == Comparison::Better;
}
- if (S.getLangOpts().CUDA && Cand1.Function && Cand2.Function) {
- FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext);
- return S.IdentifyCUDAPreference(Caller, Cand1.Function) >
- S.IdentifyCUDAPreference(Caller, Cand2.Function);
- }
-
bool HasPS1 = Cand1.Function != nullptr &&
functionHasPassObjectSizeParams(Cand1.Function);
bool HasPS2 = Cand2.Function != nullptr &&
@@ -9755,8 +9856,21 @@ bool clang::isBetterOverloadCandidate(
if (HasPS1 != HasPS2 && HasPS1)
return true;
- Comparison MV = isBetterMultiversionCandidate(Cand1, Cand2);
- return MV == Comparison::Better;
+ auto MV = isBetterMultiversionCandidate(Cand1, Cand2);
+ if (MV == Comparison::Better)
+ return true;
+ if (MV == Comparison::Worse)
+ return false;
+
+ // If other rules cannot determine which is better, CUDA preference is used
+ // to determine which is better.
+ if (S.getLangOpts().CUDA && Cand1.Function && Cand2.Function) {
+ FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext);
+ return S.IdentifyCUDAPreference(Caller, Cand1.Function) >
+ S.IdentifyCUDAPreference(Caller, Cand2.Function);
+ }
+
+ return false;
}
/// Determine whether two declarations are "equivalent" for the purposes of
@@ -9812,6 +9926,7 @@ bool Sema::isEquivalentInternalLinkageDeclaration(const NamedDecl *A,
void Sema::diagnoseEquivalentInternalLinkageDeclarations(
SourceLocation Loc, const NamedDecl *D, ArrayRef<const NamedDecl *> Equiv) {
+ assert(D && "Unknown declaration");
Diag(Loc, diag::ext_equivalent_internal_linkage_decl_in_modules) << D;
Module *M = getOwningModule(D);
@@ -9849,7 +9964,11 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
// only on their host/device attributes. Specifically, if one
// candidate call is WrongSide and the other is SameSide, we ignore
// the WrongSide candidate.
- if (S.getLangOpts().CUDA) {
+ // We only need to remove wrong-sided candidates here if
+ // -fgpu-exclude-wrong-side-overloads is off. When
+ // -fgpu-exclude-wrong-side-overloads is on, all candidates are compared
+ // uniformly in isBetterOverloadCandidate.
+ if (S.getLangOpts().CUDA && !S.getLangOpts().GPUExcludeWrongSideOverloads) {
const FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext);
bool ContainsSameSideCandidate =
llvm::any_of(Candidates, [&](OverloadCandidate *Cand) {
@@ -10110,6 +10229,27 @@ bool Sema::checkAddressOfFunctionIsAvailable(const FunctionDecl *Function,
Loc);
}
+// Don't print candidates other than the one that matches the calling
+// convention of the call operator, since that is guaranteed to exist.
+static bool shouldSkipNotingLambdaConversionDecl(FunctionDecl *Fn) {
+ const auto *ConvD = dyn_cast<CXXConversionDecl>(Fn);
+
+ if (!ConvD)
+ return false;
+ const auto *RD = cast<CXXRecordDecl>(Fn->getParent());
+ if (!RD->isLambda())
+ return false;
+
+ CXXMethodDecl *CallOp = RD->getLambdaCallOperator();
+ CallingConv CallOpCC =
+ CallOp->getType()->getAs<FunctionType>()->getCallConv();
+ QualType ConvRTy = ConvD->getType()->getAs<FunctionType>()->getReturnType();
+ CallingConv ConvToCC =
+ ConvRTy->getPointeeType()->getAs<FunctionType>()->getCallConv();
+
+ return ConvToCC != CallOpCC;
+}
+
// Notes the location of an overload candidate.
void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn,
OverloadCandidateRewriteKind RewriteKind,
@@ -10119,6 +10259,8 @@ void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn,
if (Fn->isMultiVersion() && Fn->hasAttr<TargetAttr>() &&
!Fn->getAttr<TargetAttr>()->isDefaultVersion())
return;
+ if (shouldSkipNotingLambdaConversionDecl(Fn))
+ return;
std::string FnDesc;
std::pair<OverloadCandidateKind, OverloadCandidateSelect> KSPair =
@@ -10337,7 +10479,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
}
unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
- assert(CVR && "unexpected qualifiers mismatch");
+ assert(CVR && "expected qualifiers mismatch");
if (isObjectArgument) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr_this)
@@ -10354,6 +10496,17 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
return;
}
+ if (Conv.Bad.Kind == BadConversionSequence::lvalue_ref_to_rvalue ||
+ Conv.Bad.Kind == BadConversionSequence::rvalue_ref_to_lvalue) {
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_value_category)
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (unsigned)isObjectArgument << I + 1
+ << (Conv.Bad.Kind == BadConversionSequence::rvalue_ref_to_lvalue)
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange());
+ MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
+ return;
+ }
+
// Special diagnostic for failure to convert an initializer list, since
// telling the user that it has type void is not useful.
if (FromExpr && isa<InitListExpr>(FromExpr)) {
@@ -10411,15 +10564,6 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
!ToRefTy->getPointeeType()->isIncompleteType() &&
S.IsDerivedFrom(SourceLocation(), ToRefTy->getPointeeType(), FromTy)) {
BaseToDerivedConversion = 3;
- } else if (ToTy->isLValueReferenceType() && !FromExpr->isLValue() &&
- ToTy.getNonReferenceType().getCanonicalType() ==
- FromTy.getNonReferenceType().getCanonicalType()) {
- S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_lvalue)
- << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
- << (unsigned)isObjectArgument << I + 1
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange());
- MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
- return;
}
}
@@ -10976,6 +11120,8 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
bool TakingCandidateAddress,
LangAS CtorDestAS = LangAS::Default) {
FunctionDecl *Fn = Cand->Function;
+ if (shouldSkipNotingLambdaConversionDecl(Fn))
+ return;
// Note deleted candidates, but only if they're viable.
if (Cand->Viable) {
@@ -11092,6 +11238,9 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
}
static void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
+ if (shouldSkipNotingLambdaConversionDecl(Cand->Surrogate))
+ return;
+
// 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).
@@ -11482,16 +11631,34 @@ SmallVector<OverloadCandidate *, 32> OverloadCandidateSet::CompleteCandidates(
return Cands;
}
+bool OverloadCandidateSet::shouldDeferDiags(Sema &S, ArrayRef<Expr *> Args,
+ SourceLocation OpLoc) {
+ bool DeferHint = false;
+ if (S.getLangOpts().CUDA && S.getLangOpts().GPUDeferDiag) {
+ // Defer diagnostic for CUDA/HIP if there are wrong-sided candidates or
+ // host device candidates.
+ auto WrongSidedCands =
+ CompleteCandidates(S, OCD_AllCandidates, Args, OpLoc, [](auto &Cand) {
+ return (Cand.Viable == false &&
+ Cand.FailureKind == ovl_fail_bad_target) ||
+ (Cand.Function->template hasAttr<CUDAHostAttr>() &&
+ Cand.Function->template hasAttr<CUDADeviceAttr>());
+ });
+ DeferHint = WrongSidedCands.size();
+ }
+ return DeferHint;
+}
+
/// When overload resolution fails, prints diagnostic messages containing the
/// candidates in the candidate set.
-void OverloadCandidateSet::NoteCandidates(PartialDiagnosticAt PD,
- Sema &S, OverloadCandidateDisplayKind OCD, ArrayRef<Expr *> Args,
- StringRef Opc, SourceLocation OpLoc,
+void OverloadCandidateSet::NoteCandidates(
+ PartialDiagnosticAt PD, Sema &S, OverloadCandidateDisplayKind OCD,
+ ArrayRef<Expr *> Args, StringRef Opc, SourceLocation OpLoc,
llvm::function_ref<bool(OverloadCandidate &)> Filter) {
auto Cands = CompleteCandidates(S, OCD, Args, OpLoc, Filter);
- S.Diag(PD.first, PD.second);
+ S.Diag(PD.first, PD.second, shouldDeferDiags(S, Args, OpLoc));
NoteCandidates(S, Args, Cands, Opc, OpLoc);
@@ -11543,7 +11710,9 @@ void OverloadCandidateSet::NoteCandidates(Sema &S, ArrayRef<Expr *> Args,
}
if (I != E)
- S.Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I);
+ S.Diag(OpLoc, diag::note_ovl_too_many_candidates,
+ shouldDeferDiags(S, Args, OpLoc))
+ << int(E - I);
}
static SourceLocation
@@ -12512,6 +12681,16 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
CandidateSet, PartialOverloading);
}
+/// Add the call candidates from the given set of lookup results to the given
+/// overload set. Non-function lookup results are ignored.
+void Sema::AddOverloadedCallCandidates(
+ LookupResult &R, TemplateArgumentListInfo *ExplicitTemplateArgs,
+ ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet) {
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+ AddOverloadedCallCandidate(*this, I.getPair(), ExplicitTemplateArgs, Args,
+ CandidateSet, false, /*KnownValid*/ false);
+}
+
/// Determine whether a declaration with the specified name could be moved into
/// a different namespace.
static bool canBeDeclaredInNamespace(const DeclarationName &Name) {
@@ -12531,13 +12710,11 @@ static bool canBeDeclaredInNamespace(const DeclarationName &Name) {
/// correctly implement two-stage name lookup.
///
/// Returns true if a viable candidate was found and a diagnostic was issued.
-static bool
-DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc,
- const CXXScopeSpec &SS, LookupResult &R,
- OverloadCandidateSet::CandidateSetKind CSK,
- TemplateArgumentListInfo *ExplicitTemplateArgs,
- ArrayRef<Expr *> Args,
- bool *DoDiagnoseEmptyLookup = nullptr) {
+static bool DiagnoseTwoPhaseLookup(
+ Sema &SemaRef, SourceLocation FnLoc, const CXXScopeSpec &SS,
+ LookupResult &R, OverloadCandidateSet::CandidateSetKind CSK,
+ TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
+ CXXRecordDecl **FoundInClass = nullptr) {
if (!SemaRef.inTemplateInstantiation() || !SS.isEmpty())
return false;
@@ -12550,26 +12727,32 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc,
if (!R.empty()) {
R.suppressDiagnostics();
- if (isa<CXXRecordDecl>(DC)) {
- // Don't diagnose names we find in classes; we get much better
- // diagnostics for these from DiagnoseEmptyLookup.
- R.clear();
- if (DoDiagnoseEmptyLookup)
- *DoDiagnoseEmptyLookup = true;
- return false;
- }
-
OverloadCandidateSet Candidates(FnLoc, CSK);
- for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
- AddOverloadedCallCandidate(SemaRef, I.getPair(),
- ExplicitTemplateArgs, Args,
- Candidates, false, /*KnownValid*/ false);
+ SemaRef.AddOverloadedCallCandidates(R, ExplicitTemplateArgs, Args,
+ Candidates);
OverloadCandidateSet::iterator Best;
- if (Candidates.BestViableFunction(SemaRef, FnLoc, Best) != OR_Success) {
- // No viable functions. Don't bother the user with notes for functions
- // which don't work and shouldn't be found anyway.
- R.clear();
+ OverloadingResult OR =
+ Candidates.BestViableFunction(SemaRef, FnLoc, Best);
+
+ if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
+ // We either found non-function declarations or a best viable function
+ // at class scope. A class-scope lookup result disables ADL. Don't
+ // look past this, but let the caller know that we found something that
+ // either is, or might be, usable in this class.
+ if (FoundInClass) {
+ *FoundInClass = RD;
+ if (OR == OR_Success) {
+ R.clear();
+ R.addDecl(Best->FoundDecl.getDecl(), Best->FoundDecl.getAccess());
+ R.resolveKind();
+ }
+ }
+ return false;
+ }
+
+ if (OR != OR_Success) {
+ // There wasn't a unique best function or function template.
return false;
}
@@ -12665,7 +12848,11 @@ public:
/// Attempts to recover from a call where no functions were found.
///
-/// Returns true if new candidates were found.
+/// This function will do one of three things:
+/// * Diagnose, recover, and return a recovery expression.
+/// * Diagnose, fail to recover, and return ExprError().
+/// * Do not diagnose, do not recover, and return ExprResult(). The caller is
+/// expected to diagnose as appropriate.
static ExprResult
BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
UnresolvedLookupExpr *ULE,
@@ -12678,9 +12865,8 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
//
// template <typename T> auto foo(T t) -> decltype(foo(t)) {}
// template <typename T> auto foo(T t) -> decltype(foo(&t)) {}
- //
if (SemaRef.IsBuildingRecoveryCallExpr)
- return ExprError();
+ return ExprResult();
BuildRecoveryCallExprRAII RCE(SemaRef);
CXXScopeSpec SS;
@@ -12696,10 +12882,14 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),
Sema::LookupOrdinaryName);
- bool DoDiagnoseEmptyLookup = EmptyLookup;
- if (!DiagnoseTwoPhaseLookup(
- SemaRef, Fn->getExprLoc(), SS, R, OverloadCandidateSet::CSK_Normal,
- ExplicitTemplateArgs, Args, &DoDiagnoseEmptyLookup)) {
+ CXXRecordDecl *FoundInClass = nullptr;
+ if (DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R,
+ OverloadCandidateSet::CSK_Normal,
+ ExplicitTemplateArgs, Args, &FoundInClass)) {
+ // OK, diagnosed a two-phase lookup issue.
+ } else if (EmptyLookup) {
+ // Try to recover from an empty lookup with typo correction.
+ R.clear();
NoTypoCorrectionCCC NoTypoValidator{};
FunctionCallFilterCCC FunctionCallValidator(SemaRef, Args.size(),
ExplicitTemplateArgs != nullptr,
@@ -12708,12 +12898,24 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
AllowTypoCorrection
? static_cast<CorrectionCandidateCallback &>(FunctionCallValidator)
: static_cast<CorrectionCandidateCallback &>(NoTypoValidator);
- if (!DoDiagnoseEmptyLookup ||
- SemaRef.DiagnoseEmptyLookup(S, SS, R, Validator, ExplicitTemplateArgs,
+ if (SemaRef.DiagnoseEmptyLookup(S, SS, R, Validator, ExplicitTemplateArgs,
Args))
return ExprError();
+ } else if (FoundInClass && SemaRef.getLangOpts().MSVCCompat) {
+ // We found a usable declaration of the name in a dependent base of some
+ // enclosing class.
+ // FIXME: We should also explain why the candidates found by name lookup
+ // were not viable.
+ if (SemaRef.DiagnoseDependentMemberLookup(R))
+ return ExprError();
+ } else {
+ // We had viable candidates and couldn't recover; let the caller diagnose
+ // this.
+ return ExprResult();
}
+ // If we get here, we should have issued a diagnostic and formed a recovery
+ // lookup result.
assert(!R.empty() && "lookup results empty despite recovery");
// If recovery created an ambiguity, just bail out.
@@ -12795,8 +12997,9 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
// then create a type dependent CallExpr. The goal is to postpone name
// lookup to instantiation time to be able to search into type dependent
// base classes.
- CallExpr *CE = CallExpr::Create(Context, Fn, Args, Context.DependentTy,
- VK_RValue, RParenLoc);
+ CallExpr *CE =
+ CallExpr::Create(Context, Fn, Args, Context.DependentTy, VK_RValue,
+ RParenLoc, CurFPFeatureOverrides());
CE->markDependentForPostponedNameLookup();
*Result = CE;
return true;
@@ -12818,6 +13021,8 @@ static QualType chooseRecoveryType(OverloadCandidateSet &CS,
auto ConsiderCandidate = [&](const OverloadCandidate &Candidate) {
if (!Candidate.Function)
return;
+ if (Candidate.Function->isInvalidDecl())
+ return;
QualType T = Candidate.Function->getReturnType();
if (T.isNull())
return;
@@ -12843,7 +13048,12 @@ static QualType chooseRecoveryType(OverloadCandidateSet &CS,
for (const auto &C : CS)
ConsiderCandidate(C);
- return Result.getValueOr(QualType());
+ if (!Result)
+ return QualType();
+ auto Value = Result.getValue();
+ if (Value.isNull() || Value->isUndeducedType())
+ return QualType();
+ return Value;
}
/// FinishOverloadedCallExpr - given an OverloadCandidateSet, builds and returns
@@ -12859,11 +13069,6 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
OverloadCandidateSet::iterator *Best,
OverloadingResult OverloadResult,
bool AllowTypoCorrection) {
- if (CandidateSet->empty())
- return BuildRecoveryCallExpr(SemaRef, S, Fn, ULE, LParenLoc, Args,
- RParenLoc, /*EmptyLookup=*/true,
- AllowTypoCorrection);
-
switch (OverloadResult) {
case OR_Success: {
FunctionDecl *FDecl = (*Best)->Function;
@@ -12881,9 +13086,9 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
// have meant to call.
ExprResult Recovery = BuildRecoveryCallExpr(SemaRef, S, Fn, ULE, LParenLoc,
Args, RParenLoc,
- /*EmptyLookup=*/false,
+ CandidateSet->empty(),
AllowTypoCorrection);
- if (!Recovery.isInvalid())
+ if (Recovery.isInvalid() || Recovery.isUsable())
return Recovery;
// If the user passes in a function that we can't take the address of, we
@@ -12991,7 +13196,18 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn,
static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
return Functions.size() > 1 ||
- (Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin()));
+ (Functions.size() == 1 &&
+ isa<FunctionTemplateDecl>((*Functions.begin())->getUnderlyingDecl()));
+}
+
+ExprResult Sema::CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass,
+ NestedNameSpecifierLoc NNSLoc,
+ DeclarationNameInfo DNI,
+ const UnresolvedSetImpl &Fns,
+ bool PerformADL) {
+ return UnresolvedLookupExpr::Create(Context, NamingClass, NNSLoc, DNI,
+ PerformADL, IsOverloaded(Fns),
+ Fns.begin(), Fns.end());
}
/// Create a unary operation that may resolve to an overloaded
@@ -13044,10 +13260,11 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
CurFPFeatureOverrides());
CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
- UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(
- Context, NamingClass, NestedNameSpecifierLoc(), OpNameInfo,
- /*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end());
- return CXXOperatorCallExpr::Create(Context, Op, Fn, ArgsArray,
+ ExprResult Fn = CreateUnresolvedLookupExpr(
+ NamingClass, NestedNameSpecifierLoc(), OpNameInfo, Fns);
+ if (Fn.isInvalid())
+ return ExprError();
+ return CXXOperatorCallExpr::Create(Context, Op, Fn.get(), ArgsArray,
Context.DependentTy, VK_RValue, OpLoc,
CurFPFeatureOverrides());
}
@@ -13291,14 +13508,14 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (Fns.empty()) {
// If there are no functions to store, just build a dependent
// BinaryOperator or CompoundAssignment.
- if (Opc <= BO_Assign || Opc > BO_OrAssign)
- return BinaryOperator::Create(
- Context, Args[0], Args[1], Opc, Context.DependentTy, VK_RValue,
- OK_Ordinary, OpLoc, CurFPFeatureOverrides());
- return CompoundAssignOperator::Create(
- Context, Args[0], Args[1], Opc, Context.DependentTy, VK_LValue,
- OK_Ordinary, OpLoc, CurFPFeatureOverrides(), Context.DependentTy,
- Context.DependentTy);
+ if (BinaryOperator::isCompoundAssignmentOp(Opc))
+ return CompoundAssignOperator::Create(
+ Context, Args[0], Args[1], Opc, Context.DependentTy, VK_LValue,
+ OK_Ordinary, OpLoc, CurFPFeatureOverrides(), Context.DependentTy,
+ Context.DependentTy);
+ return BinaryOperator::Create(Context, Args[0], Args[1], Opc,
+ Context.DependentTy, VK_RValue, OK_Ordinary,
+ OpLoc, CurFPFeatureOverrides());
}
// FIXME: save results of ADL from here?
@@ -13306,10 +13523,11 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// TODO: provide better source location info in DNLoc component.
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
DeclarationNameInfo OpNameInfo(OpName, OpLoc);
- UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(
- Context, NamingClass, NestedNameSpecifierLoc(), OpNameInfo,
- /*ADL*/ PerformADL, IsOverloaded(Fns), Fns.begin(), Fns.end());
- return CXXOperatorCallExpr::Create(Context, Op, Fn, Args,
+ ExprResult Fn = CreateUnresolvedLookupExpr(
+ NamingClass, NestedNameSpecifierLoc(), OpNameInfo, Fns, PerformADL);
+ if (Fn.isInvalid())
+ return ExprError();
+ return CXXOperatorCallExpr::Create(Context, Op, Fn.get(), Args,
Context.DependentTy, VK_RValue, OpLoc,
CurFPFeatureOverrides());
}
@@ -13773,15 +13991,13 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// CHECKME: no 'operator' keyword?
DeclarationNameInfo OpNameInfo(OpName, LLoc);
OpNameInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc));
- UnresolvedLookupExpr *Fn
- = UnresolvedLookupExpr::Create(Context, NamingClass,
- NestedNameSpecifierLoc(), OpNameInfo,
- /*ADL*/ true, /*Overloaded*/ false,
- UnresolvedSetIterator(),
- UnresolvedSetIterator());
+ ExprResult Fn = CreateUnresolvedLookupExpr(
+ NamingClass, NestedNameSpecifierLoc(), OpNameInfo, UnresolvedSet<0>());
+ if (Fn.isInvalid())
+ return ExprError();
// Can't add any actual overloads yet
- return CXXOperatorCallExpr::Create(Context, OO_Subscript, Fn, Args,
+ return CXXOperatorCallExpr::Create(Context, OO_Subscript, Fn.get(), Args,
Context.DependentTy, VK_RValue, RLoc,
CurFPFeatureOverrides());
}
@@ -13932,11 +14148,11 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
/// parameter). The caller needs to validate that the member
/// expression refers to a non-static member function or an overloaded
/// member function.
-ExprResult
-Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
- SourceLocation LParenLoc,
- MultiExprArg Args,
- SourceLocation RParenLoc) {
+ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
+ SourceLocation LParenLoc,
+ MultiExprArg Args,
+ SourceLocation RParenLoc,
+ bool AllowRecovery) {
assert(MemExprE->getType() == Context.BoundMemberTy ||
MemExprE->getType() == Context.OverloadTy);
@@ -13976,9 +14192,9 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
<< (qualsString.find(' ') == std::string::npos ? 1 : 2);
}
- CXXMemberCallExpr *call =
- CXXMemberCallExpr::Create(Context, MemExprE, Args, resultType,
- valueKind, RParenLoc, proto->getNumParams());
+ CXXMemberCallExpr *call = CXXMemberCallExpr::Create(
+ Context, MemExprE, Args, resultType, valueKind, RParenLoc,
+ CurFPFeatureOverrides(), proto->getNumParams());
if (CheckCallReturnType(proto->getReturnType(), op->getRHS()->getBeginLoc(),
call, nullptr))
@@ -13993,9 +14209,20 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
return MaybeBindToTemporary(call);
}
+ // We only try to build a recovery expr at this level if we can preserve
+ // the return type, otherwise we return ExprError() and let the caller
+ // recover.
+ auto BuildRecoveryExpr = [&](QualType Type) {
+ if (!AllowRecovery)
+ return ExprError();
+ std::vector<Expr *> SubExprs = {MemExprE};
+ llvm::for_each(Args, [&SubExprs](Expr *E) { SubExprs.push_back(E); });
+ return CreateRecoveryExpr(MemExprE->getBeginLoc(), RParenLoc, SubExprs,
+ Type);
+ };
if (isa<CXXPseudoDestructorExpr>(NakedMemExpr))
return CallExpr::Create(Context, MemExprE, Args, Context.VoidTy, VK_RValue,
- RParenLoc);
+ RParenLoc, CurFPFeatureOverrides());
UnbridgedCastsSet UnbridgedCasts;
if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts))
@@ -14067,6 +14294,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
UnbridgedCasts.restore();
OverloadCandidateSet::iterator Best;
+ bool Succeeded = false;
switch (CandidateSet.BestViableFunction(*this, UnresExpr->getBeginLoc(),
Best)) {
case OR_Success:
@@ -14074,7 +14302,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
FoundDecl = Best->FoundDecl;
CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
if (DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc()))
- return ExprError();
+ break;
// If FoundDecl is different from Method (such as if one is a template
// and the other a specialization), make sure DiagnoseUseOfDecl is
// called on both.
@@ -14083,7 +14311,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
// being used.
if (Method != FoundDecl.getDecl() &&
DiagnoseUseOfDecl(Method, UnresExpr->getNameLoc()))
- return ExprError();
+ break;
+ Succeeded = true;
break;
case OR_No_Viable_Function:
@@ -14093,27 +14322,25 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
PDiag(diag::err_ovl_no_viable_member_function_in_call)
<< DeclName << MemExprE->getSourceRange()),
*this, OCD_AllCandidates, Args);
- // FIXME: Leaking incoming expressions!
- return ExprError();
-
+ break;
case OR_Ambiguous:
CandidateSet.NoteCandidates(
PartialDiagnosticAt(UnresExpr->getMemberLoc(),
PDiag(diag::err_ovl_ambiguous_member_call)
<< DeclName << MemExprE->getSourceRange()),
*this, OCD_AmbiguousCandidates, Args);
- // FIXME: Leaking incoming expressions!
- return ExprError();
-
+ break;
case OR_Deleted:
CandidateSet.NoteCandidates(
PartialDiagnosticAt(UnresExpr->getMemberLoc(),
PDiag(diag::err_ovl_deleted_member_call)
<< DeclName << MemExprE->getSourceRange()),
*this, OCD_AllCandidates, Args);
- // FIXME: Leaking incoming expressions!
- return ExprError();
+ break;
}
+ // Overload resolution fails, try to recover.
+ if (!Succeeded)
+ return BuildRecoveryExpr(chooseRecoveryType(CandidateSet, &Best));
MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method);
@@ -14133,14 +14360,14 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
assert(Method && "Member call to something that isn't a method?");
const auto *Proto = Method->getType()->castAs<FunctionProtoType>();
- CXXMemberCallExpr *TheCall =
- CXXMemberCallExpr::Create(Context, MemExprE, Args, ResultType, VK,
- RParenLoc, Proto->getNumParams());
+ CXXMemberCallExpr *TheCall = CXXMemberCallExpr::Create(
+ Context, MemExprE, Args, ResultType, VK, RParenLoc,
+ CurFPFeatureOverrides(), Proto->getNumParams());
// Check for a valid return type.
if (CheckCallReturnType(Method->getReturnType(), MemExpr->getMemberLoc(),
TheCall, Method))
- return ExprError();
+ return BuildRecoveryExpr(ResultType);
// Convert the object argument (for a non-static member function call).
// We only need to do this if there was actually an overload; otherwise
@@ -14157,7 +14384,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
// Convert the rest of the arguments
if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args,
RParenLoc))
- return ExprError();
+ return BuildRecoveryExpr(ResultType);
DiagnoseSentinelCalls(Method, LParenLoc, Args);
@@ -14190,12 +14417,12 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
Diag(MemExpr->getBeginLoc(),
diag::warn_call_to_pure_virtual_member_function_from_ctor_dtor)
<< MD->getDeclName() << isa<CXXDestructorDecl>(CurContext)
- << MD->getParent()->getDeclName();
+ << MD->getParent();
Diag(MD->getBeginLoc(), diag::note_previous_decl) << MD->getDeclName();
if (getLangOpts().AppleKext)
Diag(MemExpr->getBeginLoc(), diag::note_pure_qualified_call_kext)
- << MD->getParent()->getDeclName() << MD->getDeclName();
+ << MD->getParent() << MD->getDeclName();
}
}
@@ -14377,9 +14604,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
if (Call.isInvalid())
return ExprError();
// Record usage of conversion in an implicit cast.
- Call = ImplicitCastExpr::Create(Context, Call.get()->getType(),
- CK_UserDefinedConversion, Call.get(),
- nullptr, VK_RValue);
+ Call = ImplicitCastExpr::Create(
+ Context, Call.get()->getType(), CK_UserDefinedConversion, Call.get(),
+ nullptr, VK_RValue, CurFPFeatureOverrides());
return BuildCallExpr(S, Call.get(), LParenLoc, Args, RParenLoc);
}
@@ -14678,7 +14905,7 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R,
UserDefinedLiteral *UDL = UserDefinedLiteral::Create(
Context, Fn.get(), llvm::makeArrayRef(ConvArgs, Args.size()), ResultTy,
- VK, LitEndLoc, UDSuffixLoc);
+ VK, LitEndLoc, UDSuffixLoc, CurFPFeatureOverrides());
if (CheckCallReturnType(FD->getReturnType(), UDSuffixLoc, UDL, FD))
return ExprError();
@@ -14724,12 +14951,12 @@ Sema::BuildForRangeBeginEndCall(SourceLocation Loc,
return FRS_DiagnosticIssued;
}
} else {
- UnresolvedSet<0> FoundNames;
- UnresolvedLookupExpr *Fn =
- UnresolvedLookupExpr::Create(Context, /*NamingClass=*/nullptr,
- NestedNameSpecifierLoc(), NameInfo,
- /*NeedsADL=*/true, /*Overloaded=*/false,
- FoundNames.begin(), FoundNames.end());
+ ExprResult FnR = CreateUnresolvedLookupExpr(/*NamingClass=*/nullptr,
+ NestedNameSpecifierLoc(),
+ NameInfo, UnresolvedSet<0>());
+ if (FnR.isInvalid())
+ return FRS_DiagnosticIssued;
+ UnresolvedLookupExpr *Fn = cast<UnresolvedLookupExpr>(FnR.get());
bool CandidateSetError = buildOverloadedCallSet(S, Fn, Fn, Range, Loc,
CandidateSet, CallExpr);
@@ -14784,10 +15011,9 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
if (SubExpr == ICE->getSubExpr())
return ICE;
- return ImplicitCastExpr::Create(Context, ICE->getType(),
- ICE->getCastKind(),
- SubExpr, nullptr,
- ICE->getValueKind());
+ return ImplicitCastExpr::Create(Context, ICE->getType(), ICE->getCastKind(),
+ SubExpr, nullptr, ICE->getValueKind(),
+ CurFPFeatureOverrides());
}
if (auto *GSE = dyn_cast<GenericSelectionExpr>(E)) {
diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp
index db7603b42f7b..af35052ee1e3 100644
--- a/clang/lib/Sema/SemaSYCL.cpp
+++ b/clang/lib/Sema/SemaSYCL.cpp
@@ -17,19 +17,19 @@ using namespace clang;
// SYCL device specific diagnostics implementation
// -----------------------------------------------------------------------------
-Sema::DeviceDiagBuilder Sema::SYCLDiagIfDeviceCode(SourceLocation Loc,
- unsigned DiagID) {
+Sema::SemaDiagnosticBuilder Sema::SYCLDiagIfDeviceCode(SourceLocation Loc,
+ unsigned DiagID) {
assert(getLangOpts().SYCLIsDevice &&
"Should only be called during SYCL compilation");
FunctionDecl *FD = dyn_cast<FunctionDecl>(getCurLexicalContext());
- DeviceDiagBuilder::Kind DiagKind = [this, FD] {
+ SemaDiagnosticBuilder::Kind DiagKind = [this, FD] {
if (!FD)
- return DeviceDiagBuilder::K_Nop;
+ return SemaDiagnosticBuilder::K_Nop;
if (getEmissionStatus(FD) == Sema::FunctionEmissionStatus::Emitted)
- return DeviceDiagBuilder::K_ImmediateWithCallStack;
- return DeviceDiagBuilder::K_Deferred;
+ return SemaDiagnosticBuilder::K_ImmediateWithCallStack;
+ return SemaDiagnosticBuilder::K_Deferred;
}();
- return DeviceDiagBuilder(DiagKind, Loc, DiagID, FD, *this);
+ return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, FD, *this);
}
bool Sema::checkSYCLDeviceFunction(SourceLocation Loc, FunctionDecl *Callee) {
@@ -42,8 +42,8 @@ bool Sema::checkSYCLDeviceFunction(SourceLocation Loc, FunctionDecl *Callee) {
if (isUnevaluatedContext() || isConstantEvaluated())
return true;
- DeviceDiagBuilder::Kind DiagKind = DeviceDiagBuilder::K_Nop;
+ SemaDiagnosticBuilder::Kind DiagKind = SemaDiagnosticBuilder::K_Nop;
- return DiagKind != DeviceDiagBuilder::K_Immediate &&
- DiagKind != DeviceDiagBuilder::K_ImmediateWithCallStack;
+ return DiagKind != SemaDiagnosticBuilder::K_Immediate &&
+ DiagKind != SemaDiagnosticBuilder::K_ImmediateWithCallStack;
}
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 73f3183c163f..b24a8ab110b2 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -385,6 +385,14 @@ void Sema::ActOnStartOfCompoundStmt(bool IsStmtExpr) {
PushCompoundScope(IsStmtExpr);
}
+void Sema::ActOnAfterCompoundStatementLeadingPragmas() {
+ if (getCurFPFeatures().isFPConstrained()) {
+ FunctionScopeInfo *FSI = getCurFunction();
+ assert(FSI);
+ FSI->setUsesFPIntrin();
+ }
+}
+
void Sema::ActOnFinishOfCompoundStmt() {
PopCompoundScope();
}
@@ -397,11 +405,6 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
ArrayRef<Stmt *> Elts, bool isStmtExpr) {
const unsigned NumElts = Elts.size();
- // Mark the current function as usng floating point constrained intrinsics
- if (getCurFPFeatures().isFPConstrained())
- if (FunctionDecl *F = dyn_cast<FunctionDecl>(CurContext))
- F->setUsesFPIntrin(true);
-
// If we're in C89 mode, check that we don't have any decls after stmts. If
// so, emit an extension diagnostic.
if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) {
@@ -467,7 +470,7 @@ Sema::ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val) {
ExprResult ER = E;
if (!E->isValueDependent())
- ER = VerifyIntegerConstantExpression(E);
+ ER = VerifyIntegerConstantExpression(E, AllowFold);
if (!ER.isInvalid())
ER = DefaultLvalueConversion(ER.get());
if (!ER.isInvalid())
@@ -574,11 +577,11 @@ public:
};
}
-StmtResult
-Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, Stmt *InitStmt,
- ConditionResult Cond,
- Stmt *thenStmt, SourceLocation ElseLoc,
- Stmt *elseStmt) {
+StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr,
+ SourceLocation LParenLoc, Stmt *InitStmt,
+ ConditionResult Cond, SourceLocation RParenLoc,
+ Stmt *thenStmt, SourceLocation ElseLoc,
+ Stmt *elseStmt) {
if (Cond.isInvalid())
Cond = ConditionResult(
*this, nullptr,
@@ -597,12 +600,40 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, Stmt *InitStmt,
DiagnoseEmptyStmtBody(CondExpr->getEndLoc(), thenStmt,
diag::warn_empty_if_body);
- return BuildIfStmt(IfLoc, IsConstexpr, InitStmt, Cond, thenStmt, ElseLoc,
- elseStmt);
+ if (IsConstexpr) {
+ auto DiagnoseLikelihood = [&](const Stmt *S) {
+ if (const Attr *A = Stmt::getLikelihoodAttr(S)) {
+ Diags.Report(A->getLocation(),
+ diag::warn_attribute_has_no_effect_on_if_constexpr)
+ << A << A->getRange();
+ Diags.Report(IfLoc,
+ diag::note_attribute_has_no_effect_on_if_constexpr_here)
+ << SourceRange(IfLoc, LParenLoc.getLocWithOffset(-1));
+ }
+ };
+ DiagnoseLikelihood(thenStmt);
+ DiagnoseLikelihood(elseStmt);
+ } else {
+ std::tuple<bool, const Attr *, const Attr *> LHC =
+ Stmt::determineLikelihoodConflict(thenStmt, elseStmt);
+ if (std::get<0>(LHC)) {
+ const Attr *ThenAttr = std::get<1>(LHC);
+ const Attr *ElseAttr = std::get<2>(LHC);
+ Diags.Report(ThenAttr->getLocation(),
+ diag::warn_attributes_likelihood_ifstmt_conflict)
+ << ThenAttr << ThenAttr->getRange();
+ Diags.Report(ElseAttr->getLocation(), diag::note_conflicting_attribute)
+ << ElseAttr << ElseAttr->getRange();
+ }
+ }
+
+ return BuildIfStmt(IfLoc, IsConstexpr, LParenLoc, InitStmt, Cond, RParenLoc,
+ thenStmt, ElseLoc, elseStmt);
}
StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
- Stmt *InitStmt, ConditionResult Cond,
+ SourceLocation LParenLoc, Stmt *InitStmt,
+ ConditionResult Cond, SourceLocation RParenLoc,
Stmt *thenStmt, SourceLocation ElseLoc,
Stmt *elseStmt) {
if (Cond.isInvalid())
@@ -612,7 +643,8 @@ StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
setFunctionHasBranchProtectedScope();
return IfStmt::Create(Context, IfLoc, IsConstexpr, InitStmt, Cond.get().first,
- Cond.get().second, thenStmt, ElseLoc, elseStmt);
+ Cond.get().second, LParenLoc, RParenLoc, thenStmt,
+ ElseLoc, elseStmt);
}
namespace {
@@ -640,8 +672,7 @@ static bool CmpCaseVals(const std::pair<llvm::APSInt, CaseStmt*>& lhs,
return true;
if (lhs.first == rhs.first &&
- lhs.second->getCaseLoc().getRawEncoding()
- < rhs.second->getCaseLoc().getRawEncoding())
+ lhs.second->getCaseLoc() < rhs.second->getCaseLoc())
return true;
return false;
}
@@ -739,7 +770,9 @@ ExprResult Sema::CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond) {
}
StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
- Stmt *InitStmt, ConditionResult Cond) {
+ SourceLocation LParenLoc,
+ Stmt *InitStmt, ConditionResult Cond,
+ SourceLocation RParenLoc) {
Expr *CondExpr = Cond.get().second;
assert((Cond.isInvalid() || CondExpr) && "switch with no condition");
@@ -761,7 +794,8 @@ StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
setFunctionHasBranchIntoScope();
- auto *SS = SwitchStmt::Create(Context, InitStmt, Cond.get().first, CondExpr);
+ auto *SS = SwitchStmt::Create(Context, InitStmt, Cond.get().first, CondExpr,
+ LParenLoc, RParenLoc);
getCurFunction()->SwitchStack.push_back(
FunctionScopeInfo::SwitchInfo(SS, false));
return SS;
@@ -1244,10 +1278,10 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
// Produce a nice diagnostic if multiple values aren't handled.
if (!UnhandledNames.empty()) {
- DiagnosticBuilder DB = Diag(CondExpr->getExprLoc(),
- TheDefaultStmt ? diag::warn_def_missing_case
+ auto DB = Diag(CondExpr->getExprLoc(), TheDefaultStmt
+ ? diag::warn_def_missing_case
: diag::warn_missing_case)
- << (int)UnhandledNames.size();
+ << (int)UnhandledNames.size();
for (size_t I = 0, E = std::min(UnhandledNames.size(), (size_t)3);
I != E; ++I)
@@ -1787,15 +1821,27 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
// C99 6.8.5p3: The declaration part of a 'for' statement shall only
// declare identifiers for objects having storage class 'auto' or
// 'register'.
+ const Decl *NonVarSeen = nullptr;
+ bool VarDeclSeen = false;
for (auto *DI : DS->decls()) {
- VarDecl *VD = dyn_cast<VarDecl>(DI);
- if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage())
- VD = nullptr;
- if (!VD) {
- Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for);
- DI->setInvalidDecl();
+ if (VarDecl *VD = dyn_cast<VarDecl>(DI)) {
+ VarDeclSeen = true;
+ if (VD->isLocalVarDecl() && !VD->hasLocalStorage()) {
+ Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for);
+ DI->setInvalidDecl();
+ }
+ } else if (!NonVarSeen) {
+ // Keep track of the first non-variable declaration we saw so that
+ // we can diagnose if we don't see any variable declarations. This
+ // covers a case like declaring a typedef, function, or structure
+ // type rather than a variable.
+ NonVarSeen = DI;
}
}
+ // Diagnose if we saw a non-variable declaration but no variable
+ // declarations.
+ if (NonVarSeen && !VarDeclSeen)
+ Diag(NonVarSeen->getLocation(), diag::err_non_variable_decl_in_for);
}
}
@@ -3039,12 +3085,13 @@ bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
// variable will no longer be used.
if (VD->hasAttr<BlocksAttr>()) return false;
+ // ...non-volatile...
+ if (VD->getType().isVolatileQualified())
+ return false;
+
if (CESK & CES_AllowDifferentTypes)
return true;
- // ...non-volatile...
- if (VD->getType().isVolatileQualified()) return false;
-
// Variables with higher required alignment than their type's ABI
// alignment cannot use NRVO.
if (!VD->getType()->isDependentType() && VD->hasAttr<AlignedAttr>() &&
@@ -3070,15 +3117,18 @@ bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
/// If move-initialization is not possible, such that we must fall back to
/// treating the operand as an lvalue, we will leave Res in its original
/// invalid state.
-static void TryMoveInitialization(Sema& S,
- const InitializedEntity &Entity,
+///
+/// \returns Whether we need to do the second overload resolution. If the first
+/// overload resolution fails, or if the first overload resolution succeeds but
+/// the selected constructor/operator doesn't match the additional criteria, we
+/// need to do the second overload resolution.
+static bool TryMoveInitialization(Sema &S, const InitializedEntity &Entity,
const VarDecl *NRVOCandidate,
- QualType ResultType,
- Expr *&Value,
+ QualType ResultType, Expr *&Value,
bool ConvertingConstructorsOnly,
- ExprResult &Res) {
+ bool IsDiagnosticsCheck, ExprResult &Res) {
ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(),
- CK_NoOp, Value, VK_XValue);
+ CK_NoOp, Value, VK_XValue, FPOptionsOverride());
Expr *InitExpr = &AsRvalue;
@@ -3087,8 +3137,11 @@ static void TryMoveInitialization(Sema& S,
InitializationSequence Seq(S, Entity, Kind, InitExpr);
- if (!Seq)
- return;
+ bool NeedSecondOverloadResolution = true;
+ if (!Seq &&
+ (IsDiagnosticsCheck || Seq.getFailedOverloadResult() != OR_Deleted)) {
+ return NeedSecondOverloadResolution;
+ }
for (const InitializationSequence::Step &Step : Seq.steps()) {
if (Step.Kind != InitializationSequence::SK_ConstructorInitialization &&
@@ -3131,15 +3184,19 @@ static void TryMoveInitialization(Sema& S,
}
}
+ NeedSecondOverloadResolution = false;
// Promote "AsRvalue" to the heap, since we now need this
// expression node to persist.
- Value = ImplicitCastExpr::Create(S.Context, Value->getType(), CK_NoOp,
- Value, nullptr, VK_XValue);
+ Value =
+ ImplicitCastExpr::Create(S.Context, Value->getType(), CK_NoOp, Value,
+ nullptr, VK_XValue, FPOptionsOverride());
// Complete type-checking the initialization of the return type
// using the constructor we found.
Res = Seq.Perform(S, Entity, Kind, Value);
}
+
+ return NeedSecondOverloadResolution;
}
/// Perform the initialization of a potentially-movable value, which
@@ -3164,6 +3221,7 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
// select the constructor for the copy is first performed as if the object
// were designated by an rvalue.
ExprResult Res = ExprError();
+ bool NeedSecondOverloadResolution = true;
if (AllowNRVO) {
bool AffectedByCWG1579 = false;
@@ -3180,15 +3238,14 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
}
if (NRVOCandidate) {
- TryMoveInitialization(*this, Entity, NRVOCandidate, ResultType, Value,
- true, Res);
+ NeedSecondOverloadResolution = TryMoveInitialization(
+ *this, Entity, NRVOCandidate, ResultType, Value, true, false, Res);
}
- if (!Res.isInvalid() && AffectedByCWG1579) {
+ if (!NeedSecondOverloadResolution && AffectedByCWG1579) {
QualType QT = NRVOCandidate->getType();
- if (QT.getNonReferenceType()
- .getUnqualifiedType()
- .isTriviallyCopyableType(Context)) {
+ if (QT.getNonReferenceType().getUnqualifiedType().isTriviallyCopyableType(
+ Context)) {
// Adding 'std::move' around a trivially copyable variable is probably
// pointless. Don't suggest it.
} else {
@@ -3202,12 +3259,12 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
Str += NRVOCandidate->getDeclName().getAsString();
Str += ")";
Diag(Value->getExprLoc(), diag::warn_return_std_move_in_cxx11)
- << Value->getSourceRange()
- << NRVOCandidate->getDeclName() << ResultType << QT;
+ << Value->getSourceRange() << NRVOCandidate->getDeclName()
+ << ResultType << QT;
Diag(Value->getExprLoc(), diag::note_add_std_move_in_cxx11)
<< FixItHint::CreateReplacement(Value->getSourceRange(), Str);
}
- } else if (Res.isInvalid() &&
+ } else if (NeedSecondOverloadResolution &&
!getDiagnostics().isIgnored(diag::warn_return_std_move,
Value->getExprLoc())) {
const VarDecl *FakeNRVOCandidate =
@@ -3226,7 +3283,7 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
ExprResult FakeRes = ExprError();
Expr *FakeValue = Value;
TryMoveInitialization(*this, Entity, FakeNRVOCandidate, ResultType,
- FakeValue, false, FakeRes);
+ FakeValue, false, true, FakeRes);
if (!FakeRes.isInvalid()) {
bool IsThrow =
(Entity.getKind() == InitializedEntity::EK_Exception);
@@ -3248,7 +3305,7 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
// Either we didn't meet the criteria for treating an lvalue as an rvalue,
// above, or overload resolution failed. Either way, we need to try
// (again) now with the return value expression as written.
- if (Res.isInvalid())
+ if (NeedSecondOverloadResolution)
Res = PerformCopyInitialization(Entity, SourceLocation(), Value);
return Res;
@@ -3290,9 +3347,14 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
}
if (HasDeducedReturnType) {
+ FunctionDecl *FD = CurLambda->CallOperator;
+ // If we've already decided this lambda is invalid, e.g. because
+ // we saw a `return` whose expression had an error, don't keep
+ // trying to deduce its return type.
+ if (FD->isInvalidDecl())
+ return StmtError();
// In C++1y, the return type may involve 'auto'.
// FIXME: Blocks might have a return type of 'auto' explicitly specified.
- FunctionDecl *FD = CurLambda->CallOperator;
if (CurCap->ReturnType.isNull())
CurCap->ReturnType = FD->getReturnType();
@@ -3587,7 +3649,8 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
Scope *CurScope) {
// Correct typos, in case the containing function returns 'auto' and
// RetValExp should determine the deduced type.
- ExprResult RetVal = CorrectDelayedTyposInExpr(RetValExp);
+ ExprResult RetVal = CorrectDelayedTyposInExpr(
+ RetValExp, nullptr, /*RecoverUncorrectedTypos=*/true);
if (RetVal.isInvalid())
return StmtError();
StmtResult R = BuildReturnStmt(ReturnLoc, RetVal.get());
@@ -3625,12 +3688,11 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (FD->hasAttrs())
Attrs = &FD->getAttrs();
if (FD->isNoReturn())
- Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr)
- << FD->getDeclName();
+ Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr) << FD;
if (FD->isMain() && RetValExp)
if (isa<CXXBoolLiteralExpr>(RetValExp))
Diag(ReturnLoc, diag::warn_main_returns_bool_literal)
- << RetValExp->getSourceRange();
+ << RetValExp->getSourceRange();
if (FD->hasAttr<CmseNSEntryAttr>() && RetValExp) {
if (const auto *RT = dyn_cast<RecordType>(FnRetType.getCanonicalType())) {
if (RT->getDecl()->isOrContainsUnion())
@@ -3673,6 +3735,11 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (getLangOpts().CPlusPlus14) {
if (AutoType *AT = FnRetType->getContainedAutoType()) {
FunctionDecl *FD = cast<FunctionDecl>(CurContext);
+ // If we've already decided this function is invalid, e.g. because
+ // we saw a `return` whose expression had an error, don't keep
+ // trying to deduce its return type.
+ if (FD->isInvalidDecl())
+ return StmtError();
if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {
FD->setInvalidDecl();
return StmtError();
@@ -3701,8 +3768,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
FunctionKind = 3;
Diag(ReturnLoc, diag::err_return_init_list)
- << CurDecl->getDeclName() << FunctionKind
- << RetValExp->getSourceRange();
+ << CurDecl << FunctionKind << RetValExp->getSourceRange();
// Drop the expression.
RetValExp = nullptr;
@@ -3729,9 +3795,8 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// return of void in constructor/destructor is illegal in C++.
if (D == diag::err_ctor_dtor_returns_void) {
NamedDecl *CurDecl = getCurFunctionOrMethodDecl();
- Diag(ReturnLoc, D)
- << CurDecl->getDeclName() << isa<CXXDestructorDecl>(CurDecl)
- << RetValExp->getSourceRange();
+ Diag(ReturnLoc, D) << CurDecl << isa<CXXDestructorDecl>(CurDecl)
+ << RetValExp->getSourceRange();
}
// return (some void expression); is legal in C++.
else if (D != diag::ext_return_has_void_expr ||
@@ -3747,8 +3812,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
FunctionKind = 3;
Diag(ReturnLoc, D)
- << CurDecl->getDeclName() << FunctionKind
- << RetValExp->getSourceRange();
+ << CurDecl << FunctionKind << RetValExp->getSourceRange();
}
}
@@ -3766,25 +3830,26 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
} else if (!RetValExp && !HasDependentReturnType) {
FunctionDecl *FD = getCurFunctionDecl();
- unsigned DiagID;
if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) {
// C++11 [stmt.return]p2
- DiagID = diag::err_constexpr_return_missing_expr;
+ Diag(ReturnLoc, diag::err_constexpr_return_missing_expr)
+ << FD << FD->isConsteval();
FD->setInvalidDecl();
- } else if (getLangOpts().C99) {
- // C99 6.8.6.4p1 (ext_ since GCC warns)
- DiagID = diag::ext_return_missing_expr;
} else {
+ // C99 6.8.6.4p1 (ext_ since GCC warns)
// C90 6.6.6.4p4
- DiagID = diag::warn_return_missing_expr;
+ unsigned DiagID = getLangOpts().C99 ? diag::ext_return_missing_expr
+ : diag::warn_return_missing_expr;
+ // Note that at this point one of getCurFunctionDecl() or
+ // getCurMethodDecl() must be non-null (see above).
+ assert((getCurFunctionDecl() || getCurMethodDecl()) &&
+ "Not in a FunctionDecl or ObjCMethodDecl?");
+ bool IsMethod = FD == nullptr;
+ const NamedDecl *ND =
+ IsMethod ? cast<NamedDecl>(getCurMethodDecl()) : cast<NamedDecl>(FD);
+ Diag(ReturnLoc, DiagID) << ND << IsMethod;
}
- if (FD)
- Diag(ReturnLoc, DiagID)
- << FD->getIdentifier() << 0 /*fn*/ << FD->isConsteval();
- else
- Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/;
-
Result = ReturnStmt::Create(Context, ReturnLoc, /* RetExpr=*/nullptr,
/* NRVOCandidate=*/nullptr);
} else {
diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp
index 10fa24682f9c..3b631bf747c6 100644
--- a/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/clang/lib/Sema/SemaStmtAsm.cpp
@@ -448,9 +448,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
unsigned Size = Context.getTypeSize(Ty);
if (!Context.getTargetInfo().validateInputSize(FeatureMap,
Literal->getString(), Size))
- return StmtResult(
- targetDiag(InputExpr->getBeginLoc(), diag::err_asm_invalid_input_size)
- << Info.getConstraintStr());
+ return targetDiag(InputExpr->getBeginLoc(),
+ diag::err_asm_invalid_input_size)
+ << Info.getConstraintStr();
}
// Check that the clobbers are valid.
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index e9d3c755eb23..8031aa6b0ece 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -10,13 +10,14 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/EvaluatedExprVisitor.h"
-#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/StringExtras.h"
using namespace clang;
@@ -139,10 +140,18 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
LoopHintAttr::PipelineInitiationInterval)
.Case("distribute", LoopHintAttr::Distribute)
.Default(LoopHintAttr::Vectorize);
- if (Option == LoopHintAttr::VectorizeWidth ||
- Option == LoopHintAttr::InterleaveCount ||
- Option == LoopHintAttr::UnrollCount ||
- Option == LoopHintAttr::PipelineInitiationInterval) {
+ if (Option == LoopHintAttr::VectorizeWidth) {
+ assert((ValueExpr || (StateLoc && StateLoc->Ident)) &&
+ "Attribute must have a valid value expression or argument.");
+ if (ValueExpr && S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc()))
+ return nullptr;
+ if (StateLoc && StateLoc->Ident && StateLoc->Ident->isStr("scalable"))
+ State = LoopHintAttr::ScalableWidth;
+ else
+ State = LoopHintAttr::FixedWidth;
+ } else if (Option == LoopHintAttr::InterleaveCount ||
+ Option == LoopHintAttr::UnrollCount ||
+ Option == LoopHintAttr::PipelineInitiationInterval) {
assert(ValueExpr && "Attribute must have a valid value expression.");
if (S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc()))
return nullptr;
@@ -183,6 +192,7 @@ public:
bool foundCallExpr() { return FoundCallExpr; }
void VisitCallExpr(const CallExpr *E) { FoundCallExpr = true; }
+ void VisitAsmStmt(const AsmStmt *S) { FoundCallExpr = true; }
void Visit(const Stmt *St) {
if (!St)
@@ -209,6 +219,24 @@ static Attr *handleNoMergeAttr(Sema &S, Stmt *St, const ParsedAttr &A,
return ::new (S.Context) NoMergeAttr(S.Context, A);
}
+static Attr *handleLikely(Sema &S, Stmt *St, const ParsedAttr &A,
+ SourceRange Range) {
+
+ if (!S.getLangOpts().CPlusPlus20 && A.isCXX11Attribute() && !A.getScopeName())
+ S.Diag(A.getLoc(), diag::ext_cxx20_attr) << A << Range;
+
+ return ::new (S.Context) LikelyAttr(S.Context, A);
+}
+
+static Attr *handleUnlikely(Sema &S, Stmt *St, const ParsedAttr &A,
+ SourceRange Range) {
+
+ if (!S.getLangOpts().CPlusPlus20 && A.isCXX11Attribute() && !A.getScopeName())
+ S.Diag(A.getLoc(), diag::ext_cxx20_attr) << A << Range;
+
+ return ::new (S.Context) UnlikelyAttr(S.Context, A);
+}
+
static void
CheckForIncompatibleAttributes(Sema &S,
const SmallVectorImpl<const Attr *> &Attrs) {
@@ -314,6 +342,32 @@ CheckForIncompatibleAttributes(Sema &S,
<< CategoryState.NumericAttr->getDiagnosticName(Policy);
}
}
+
+ // C++20 [dcl.attr.likelihood]p1 The attribute-token likely shall not appear
+ // in an attribute-specifier-seq that contains the attribute-token unlikely.
+ const LikelyAttr *Likely = nullptr;
+ const UnlikelyAttr *Unlikely = nullptr;
+ for (const auto *I : Attrs) {
+ if (const auto *Attr = dyn_cast<LikelyAttr>(I)) {
+ if (Unlikely) {
+ S.Diag(Attr->getLocation(), diag::err_attributes_are_not_compatible)
+ << Attr << Unlikely << Attr->getRange();
+ S.Diag(Unlikely->getLocation(), diag::note_conflicting_attribute)
+ << Unlikely->getRange();
+ return;
+ }
+ Likely = Attr;
+ } else if (const auto *Attr = dyn_cast<UnlikelyAttr>(I)) {
+ if (Likely) {
+ S.Diag(Attr->getLocation(), diag::err_attributes_are_not_compatible)
+ << Attr << Likely << Attr->getRange();
+ S.Diag(Likely->getLocation(), diag::note_conflicting_attribute)
+ << Likely->getRange();
+ return;
+ }
+ Unlikely = Attr;
+ }
+ }
}
static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A,
@@ -335,15 +389,15 @@ static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A,
if (NumArgs == 1) {
Expr *E = A.getArgAsExpr(0);
- llvm::APSInt ArgVal(32);
+ Optional<llvm::APSInt> ArgVal;
- if (!E->isIntegerConstantExpr(ArgVal, S.Context)) {
+ if (!(ArgVal = E->getIntegerConstantExpr(S.Context))) {
S.Diag(A.getLoc(), diag::err_attribute_argument_type)
<< A << AANT_ArgumentIntegerConstant << E->getSourceRange();
return nullptr;
}
- int Val = ArgVal.getSExtValue();
+ int Val = ArgVal->getSExtValue();
if (Val <= 0) {
S.Diag(A.getRange().getBegin(),
@@ -364,7 +418,7 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
S.Diag(A.getLoc(), A.isDeclspecAttribute()
? (unsigned)diag::warn_unhandled_ms_attribute_ignored
: (unsigned)diag::warn_unknown_attribute_ignored)
- << A;
+ << A << A.getRange();
return nullptr;
case ParsedAttr::AT_FallThrough:
return handleFallThroughAttr(S, St, A, Range);
@@ -376,6 +430,10 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
return handleSuppressAttr(S, St, A, Range);
case ParsedAttr::AT_NoMerge:
return handleNoMergeAttr(S, St, A, Range);
+ case ParsedAttr::AT_Likely:
+ return handleLikely(S, St, A, Range);
+ case ParsedAttr::AT_Unlikely:
+ return handleUnlikely(S, St, A, Range);
default:
// if we're here, then we parsed a known attribute, but didn't recognize
// it as a statement attribute => it is declaration attribute
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index c05ed0b14e3e..12880b95b9c6 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -23,6 +23,7 @@
#include "clang/Basic/Stack.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Overload.h"
#include "clang/Sema/ParsedTemplate.h"
@@ -938,11 +939,10 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
TArg = TemplateArgument(Template, Optional<unsigned int>());
else
TArg = Template;
- return TemplateArgumentLoc(TArg,
- Arg.getScopeSpec().getWithLocInContext(
- SemaRef.Context),
- Arg.getLocation(),
- Arg.getEllipsisLoc());
+ return TemplateArgumentLoc(
+ SemaRef.Context, TArg,
+ Arg.getScopeSpec().getWithLocInContext(SemaRef.Context),
+ Arg.getLocation(), Arg.getEllipsisLoc());
}
}
@@ -1176,7 +1176,11 @@ static ExprResult formImmediatelyDeclaredConstraint(
// template<C1... T> struct s1;
//
// The constraint: (C1<T> && ...)
- return S.BuildCXXFoldExpr(/*LParenLoc=*/SourceLocation(),
+ //
+ // Note that the type of C1<T> is known to be 'bool', so we don't need to do
+ // any unqualified lookups for 'operator&&' here.
+ return S.BuildCXXFoldExpr(/*UnqualifiedLookup=*/nullptr,
+ /*LParenLoc=*/SourceLocation(),
ImmediatelyDeclaredConstraint.get(), BO_LAnd,
EllipsisLoc, /*RHS=*/nullptr,
/*RParenLoc=*/SourceLocation(),
@@ -1274,6 +1278,108 @@ QualType Sema::CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
return CheckNonTypeTemplateParameterType(TSI->getType(), Loc);
}
+/// Require the given type to be a structural type, and diagnose if it is not.
+///
+/// \return \c true if an error was produced.
+bool Sema::RequireStructuralType(QualType T, SourceLocation Loc) {
+ if (T->isDependentType())
+ return false;
+
+ if (RequireCompleteType(Loc, T, diag::err_template_nontype_parm_incomplete))
+ return true;
+
+ if (T->isStructuralType())
+ return false;
+
+ // Structural types are required to be object types or lvalue references.
+ if (T->isRValueReferenceType()) {
+ Diag(Loc, diag::err_template_nontype_parm_rvalue_ref) << T;
+ return true;
+ }
+
+ // Don't mention structural types in our diagnostic prior to C++20. Also,
+ // there's not much more we can say about non-scalar non-class types --
+ // because we can't see functions or arrays here, those can only be language
+ // extensions.
+ if (!getLangOpts().CPlusPlus20 ||
+ (!T->isScalarType() && !T->isRecordType())) {
+ Diag(Loc, diag::err_template_nontype_parm_bad_type) << T;
+ return true;
+ }
+
+ // Structural types are required to be literal types.
+ if (RequireLiteralType(Loc, T, diag::err_template_nontype_parm_not_literal))
+ return true;
+
+ Diag(Loc, diag::err_template_nontype_parm_not_structural) << T;
+
+ // Drill down into the reason why the class is non-structural.
+ while (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) {
+ // All members are required to be public and non-mutable, and can't be of
+ // rvalue reference type. Check these conditions first to prefer a "local"
+ // reason over a more distant one.
+ for (const FieldDecl *FD : RD->fields()) {
+ if (FD->getAccess() != AS_public) {
+ Diag(FD->getLocation(), diag::note_not_structural_non_public) << T << 0;
+ return true;
+ }
+ if (FD->isMutable()) {
+ Diag(FD->getLocation(), diag::note_not_structural_mutable_field) << T;
+ return true;
+ }
+ if (FD->getType()->isRValueReferenceType()) {
+ Diag(FD->getLocation(), diag::note_not_structural_rvalue_ref_field)
+ << T;
+ return true;
+ }
+ }
+
+ // All bases are required to be public.
+ for (const auto &BaseSpec : RD->bases()) {
+ if (BaseSpec.getAccessSpecifier() != AS_public) {
+ Diag(BaseSpec.getBaseTypeLoc(), diag::note_not_structural_non_public)
+ << T << 1;
+ return true;
+ }
+ }
+
+ // All subobjects are required to be of structural types.
+ SourceLocation SubLoc;
+ QualType SubType;
+ int Kind = -1;
+
+ for (const FieldDecl *FD : RD->fields()) {
+ QualType T = Context.getBaseElementType(FD->getType());
+ if (!T->isStructuralType()) {
+ SubLoc = FD->getLocation();
+ SubType = T;
+ Kind = 0;
+ break;
+ }
+ }
+
+ if (Kind == -1) {
+ for (const auto &BaseSpec : RD->bases()) {
+ QualType T = BaseSpec.getType();
+ if (!T->isStructuralType()) {
+ SubLoc = BaseSpec.getBaseTypeLoc();
+ SubType = T;
+ Kind = 1;
+ break;
+ }
+ }
+ }
+
+ assert(Kind != -1 && "couldn't find reason why type is not structural");
+ Diag(SubLoc, diag::note_not_structural_subobject)
+ << T << Kind << SubType;
+ T = SubType;
+ RD = T->getAsCXXRecordDecl();
+ }
+
+ return true;
+}
+
QualType Sema::CheckNonTypeTemplateParameterType(QualType T,
SourceLocation Loc) {
// We don't allow variably-modified types as the type of non-type template
@@ -1293,13 +1399,13 @@ QualType Sema::CheckNonTypeTemplateParameterType(QualType T,
if (T->isIntegralOrEnumerationType() ||
// -- pointer to object or pointer to function,
T->isPointerType() ||
- // -- reference to object or reference to function,
- T->isReferenceType() ||
+ // -- lvalue reference to object or lvalue reference to function,
+ T->isLValueReferenceType() ||
// -- pointer to member,
T->isMemberPointerType() ||
- // -- std::nullptr_t.
+ // -- std::nullptr_t, or
T->isNullPtrType() ||
- // Allow use of auto in template parameter declarations.
+ // -- a type that contains a placeholder type.
T->isUndeducedType()) {
// C++ [temp.param]p5: The top-level cv-qualifiers on the template-parameter
// are ignored when determining its type.
@@ -1323,10 +1429,21 @@ QualType Sema::CheckNonTypeTemplateParameterType(QualType T,
if (T->isDependentType())
return T.getUnqualifiedType();
- Diag(Loc, diag::err_template_nontype_parm_bad_type)
- << T;
+ // C++20 [temp.param]p6:
+ // -- a structural type
+ if (RequireStructuralType(T, Loc))
+ return QualType();
+
+ if (!getLangOpts().CPlusPlus20) {
+ // FIXME: Consider allowing structural types as an extension in C++17. (In
+ // earlier language modes, the template argument evaluation rules are too
+ // inflexible.)
+ Diag(Loc, diag::err_template_nontype_parm_bad_structural_type) << T;
+ return QualType();
+ }
- return QualType();
+ Diag(Loc, diag::warn_cxx17_compat_template_nontype_parm_type) << T;
+ return T.getUnqualifiedType();
}
NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
@@ -1960,27 +2077,27 @@ public:
QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) {
ASTContext &Context = SemaRef.getASTContext();
TypedefNameDecl *OrigDecl = TL.getTypedefNameDecl();
- TypeLocBuilder InnerTLB;
- QualType Transformed =
- TransformType(InnerTLB, OrigDecl->getTypeSourceInfo()->getTypeLoc());
- TypeSourceInfo *TSI =
- TransformType(InnerTLB.getTypeSourceInfo(Context, Transformed));
-
- TypedefNameDecl *Decl = nullptr;
-
- if (isa<TypeAliasDecl>(OrigDecl))
- Decl = TypeAliasDecl::Create(
- Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(),
- OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI);
- else {
- assert(isa<TypedefDecl>(OrigDecl) && "Not a Type alias or typedef");
- Decl = TypedefDecl::Create(
- Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(),
- OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI);
+ TypedefNameDecl *Decl = OrigDecl;
+ // Transform the underlying type of the typedef and clone the Decl only if
+ // the typedef has a dependent context.
+ if (OrigDecl->getDeclContext()->isDependentContext()) {
+ TypeLocBuilder InnerTLB;
+ QualType Transformed =
+ TransformType(InnerTLB, OrigDecl->getTypeSourceInfo()->getTypeLoc());
+ TypeSourceInfo *TSI = InnerTLB.getTypeSourceInfo(Context, Transformed);
+ if (isa<TypeAliasDecl>(OrigDecl))
+ Decl = TypeAliasDecl::Create(
+ Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(),
+ OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI);
+ else {
+ assert(isa<TypedefDecl>(OrigDecl) && "Not a Type alias or typedef");
+ Decl = TypedefDecl::Create(
+ Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(),
+ OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI);
+ }
+ MaterializedTypedefs.push_back(Decl);
}
- MaterializedTypedefs.push_back(Decl);
-
QualType TDTy = Context.getTypedefType(Decl);
TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(TDTy);
TypedefTL.setNameLoc(TL.getNameLoc());
@@ -3544,7 +3661,6 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
QualType CanonType;
- bool InstantiationDependent = false;
if (TypeAliasTemplateDecl *AliasTemplate =
dyn_cast<TypeAliasTemplateDecl>(Template)) {
@@ -3607,7 +3723,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
}
} else if (Name.isDependent() ||
TemplateSpecializationType::anyDependentTemplateArguments(
- TemplateArgs, InstantiationDependent)) {
+ TemplateArgs, Converted)) {
// This class template specialization is a dependent
// type. Therefore, its canonical type is another class template
// specialization type that contains all of the converted
@@ -3675,11 +3791,15 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext());
}
- if (Decl->getSpecializationKind() == TSK_Undeclared) {
- MultiLevelTemplateArgumentList TemplateArgLists;
- TemplateArgLists.addOuterTemplateArguments(Converted);
- InstantiateAttrsForDecl(TemplateArgLists, ClassTemplate->getTemplatedDecl(),
- Decl);
+ if (Decl->getSpecializationKind() == TSK_Undeclared &&
+ ClassTemplate->getTemplatedDecl()->hasAttrs()) {
+ InstantiatingTemplate Inst(*this, TemplateLoc, Decl);
+ if (!Inst.isInvalid()) {
+ MultiLevelTemplateArgumentList TemplateArgLists;
+ TemplateArgLists.addOuterTemplateArguments(Converted);
+ InstantiateAttrsForDecl(TemplateArgLists,
+ ClassTemplate->getTemplatedDecl(), Decl);
+ }
}
// Diagnose uses of this specialization.
@@ -4194,11 +4314,9 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
// FIXME: Move these checks to CheckTemplatePartialSpecializationArgs so we
// also do them during instantiation.
- bool InstantiationDependent;
if (!Name.isDependent() &&
- !TemplateSpecializationType::anyDependentTemplateArguments(
- TemplateArgs.arguments(),
- InstantiationDependent)) {
+ !TemplateSpecializationType::anyDependentTemplateArguments(TemplateArgs,
+ Converted)) {
Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
<< VarTemplate->getDeclName();
IsPartialSpecialization = false;
@@ -4358,6 +4476,12 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
Converted, /*UpdateArgsWithConversion=*/true))
return true;
+ // Produce a placeholder value if the specialization is dependent.
+ if (Template->getDeclContext()->isDependentContext() ||
+ TemplateSpecializationType::anyDependentTemplateArguments(TemplateArgs,
+ Converted))
+ return DeclResult();
+
// Find the variable template specialization declaration that
// corresponds to these arguments.
void *InsertPos = nullptr;
@@ -4385,84 +4509,75 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
// 1. Attempt to find the closest partial specialization that this
// specializes, if any.
- // If any of the template arguments is dependent, then this is probably
- // a placeholder for an incomplete declarative context; which must be
- // complete by instantiation time. Thus, do not search through the partial
- // specializations yet.
// TODO: Unify with InstantiateClassTemplateSpecialization()?
// Perhaps better after unification of DeduceTemplateArguments() and
// getMoreSpecializedPartialSpecialization().
- bool InstantiationDependent = false;
- if (!TemplateSpecializationType::anyDependentTemplateArguments(
- TemplateArgs, InstantiationDependent)) {
+ SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs;
+ Template->getPartialSpecializations(PartialSpecs);
- SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs;
- Template->getPartialSpecializations(PartialSpecs);
-
- for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
- VarTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
- TemplateDeductionInfo Info(FailedCandidates.getLocation());
+ for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
+ VarTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
+ TemplateDeductionInfo Info(FailedCandidates.getLocation());
- if (TemplateDeductionResult Result =
- DeduceTemplateArguments(Partial, TemplateArgList, Info)) {
- // Store the failed-deduction information for use in diagnostics, later.
- // TODO: Actually use the failed-deduction info?
- FailedCandidates.addCandidate().set(
- DeclAccessPair::make(Template, AS_public), Partial,
- MakeDeductionFailureInfo(Context, Result, Info));
- (void)Result;
- } else {
- Matched.push_back(PartialSpecMatchResult());
- Matched.back().Partial = Partial;
- Matched.back().Args = Info.take();
- }
+ if (TemplateDeductionResult Result =
+ DeduceTemplateArguments(Partial, TemplateArgList, Info)) {
+ // Store the failed-deduction information for use in diagnostics, later.
+ // TODO: Actually use the failed-deduction info?
+ FailedCandidates.addCandidate().set(
+ DeclAccessPair::make(Template, AS_public), Partial,
+ MakeDeductionFailureInfo(Context, Result, Info));
+ (void)Result;
+ } else {
+ Matched.push_back(PartialSpecMatchResult());
+ Matched.back().Partial = Partial;
+ Matched.back().Args = Info.take();
}
+ }
- if (Matched.size() >= 1) {
- SmallVector<MatchResult, 4>::iterator Best = Matched.begin();
- if (Matched.size() == 1) {
- // -- If exactly one matching specialization is found, the
- // instantiation is generated from that specialization.
- // We don't need to do anything for this.
- } else {
- // -- If more than one matching specialization is found, the
- // partial order rules (14.5.4.2) are used to determine
- // whether one of the specializations is more specialized
- // than the others. If none of the specializations is more
- // specialized than all of the other matching
- // specializations, then the use of the variable template is
- // ambiguous and the program is ill-formed.
- for (SmallVector<MatchResult, 4>::iterator P = Best + 1,
- PEnd = Matched.end();
- P != PEnd; ++P) {
- if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
- PointOfInstantiation) ==
- P->Partial)
- Best = P;
- }
+ if (Matched.size() >= 1) {
+ SmallVector<MatchResult, 4>::iterator Best = Matched.begin();
+ if (Matched.size() == 1) {
+ // -- If exactly one matching specialization is found, the
+ // instantiation is generated from that specialization.
+ // We don't need to do anything for this.
+ } else {
+ // -- If more than one matching specialization is found, the
+ // partial order rules (14.5.4.2) are used to determine
+ // whether one of the specializations is more specialized
+ // than the others. If none of the specializations is more
+ // specialized than all of the other matching
+ // specializations, then the use of the variable template is
+ // ambiguous and the program is ill-formed.
+ for (SmallVector<MatchResult, 4>::iterator P = Best + 1,
+ PEnd = Matched.end();
+ P != PEnd; ++P) {
+ if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
+ PointOfInstantiation) ==
+ P->Partial)
+ Best = P;
+ }
- // Determine if the best partial specialization is more specialized than
- // the others.
- for (SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
- PEnd = Matched.end();
- P != PEnd; ++P) {
- if (P != Best && getMoreSpecializedPartialSpecialization(
- P->Partial, Best->Partial,
- PointOfInstantiation) != Best->Partial) {
- AmbiguousPartialSpec = true;
- break;
- }
+ // Determine if the best partial specialization is more specialized than
+ // the others.
+ for (SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
+ PEnd = Matched.end();
+ P != PEnd; ++P) {
+ if (P != Best && getMoreSpecializedPartialSpecialization(
+ P->Partial, Best->Partial,
+ PointOfInstantiation) != Best->Partial) {
+ AmbiguousPartialSpec = true;
+ break;
}
}
-
- // Instantiate using the best variable template partial specialization.
- InstantiationPattern = Best->Partial;
- InstantiationArgs = Best->Args;
- } else {
- // -- If no match is found, the instantiation is generated
- // from the primary template.
- // InstantiationPattern = Template->getTemplatedDecl();
}
+
+ // Instantiate using the best variable template partial specialization.
+ InstantiationPattern = Best->Partial;
+ InstantiationArgs = Best->Args;
+ } else {
+ // -- If no match is found, the instantiation is generated
+ // from the primary template.
+ // InstantiationPattern = Template->getTemplatedDecl();
}
// 2. Create the canonical declaration.
@@ -4471,7 +4586,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
// FIXME: LateAttrs et al.?
VarTemplateSpecializationDecl *Decl = BuildVarTemplateInstantiation(
Template, InstantiationPattern, *InstantiationArgs, TemplateArgs,
- Converted, TemplateNameLoc, InsertPos /*, LateAttrs, StartingScope*/);
+ Converted, TemplateNameLoc /*, LateAttrs, StartingScope*/);
if (!Decl)
return true;
@@ -4510,6 +4625,9 @@ Sema::CheckVarTemplateId(const CXXScopeSpec &SS,
if (Decl.isInvalid())
return ExprError();
+ if (!Decl.get())
+ return ExprResult();
+
VarDecl *Var = cast<VarDecl>(Decl.get());
if (!Var->getTemplateSpecializationKind())
Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation,
@@ -4547,22 +4665,16 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
return ExprError();
ConstraintSatisfaction Satisfaction;
- bool AreArgsDependent = false;
- for (TemplateArgument &Arg : Converted) {
- if (Arg.isDependent()) {
- AreArgsDependent = true;
- break;
- }
- }
+ bool AreArgsDependent =
+ TemplateSpecializationType::anyDependentTemplateArguments(*TemplateArgs,
+ Converted);
if (!AreArgsDependent &&
- CheckConstraintSatisfaction(NamedConcept,
- {NamedConcept->getConstraintExpr()},
- Converted,
- SourceRange(SS.isSet() ? SS.getBeginLoc() :
- ConceptNameInfo.getLoc(),
- TemplateArgs->getRAngleLoc()),
- Satisfaction))
- return ExprError();
+ CheckConstraintSatisfaction(
+ NamedConcept, {NamedConcept->getConstraintExpr()}, Converted,
+ SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameInfo.getLoc(),
+ TemplateArgs->getRAngleLoc()),
+ Satisfaction))
+ return ExprError();
return ConceptSpecializationExpr::Create(Context,
SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc{},
@@ -4597,18 +4709,14 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
}
}
- auto AnyDependentArguments = [&]() -> bool {
- bool InstantiationDependent;
- return TemplateArgs &&
- TemplateSpecializationType::anyDependentTemplateArguments(
- *TemplateArgs, InstantiationDependent);
- };
-
// In C++1y, check variable template ids.
- if (R.getAsSingle<VarTemplateDecl>() && !AnyDependentArguments()) {
- return CheckVarTemplateId(SS, R.getLookupNameInfo(),
- R.getAsSingle<VarTemplateDecl>(),
- TemplateKWLoc, TemplateArgs);
+ if (R.getAsSingle<VarTemplateDecl>()) {
+ ExprResult Res = CheckVarTemplateId(SS, R.getLookupNameInfo(),
+ R.getAsSingle<VarTemplateDecl>(),
+ TemplateKWLoc, TemplateArgs);
+ if (Res.isInvalid() || Res.isUsable())
+ return Res;
+ // Result is dependent. Carry on to build an UnresolvedLookupEpxr.
}
if (R.getAsSingle<ConceptDecl>()) {
@@ -5158,15 +5266,17 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
if (TName.isNull())
return TemplateArgumentLoc();
- return TemplateArgumentLoc(TemplateArgument(TName),
- TempTempParm->getDefaultArgument().getTemplateQualifierLoc(),
- TempTempParm->getDefaultArgument().getTemplateNameLoc());
+ return TemplateArgumentLoc(
+ Context, TemplateArgument(TName),
+ TempTempParm->getDefaultArgument().getTemplateQualifierLoc(),
+ TempTempParm->getDefaultArgument().getTemplateNameLoc());
}
/// Convert a template-argument that we parsed as a type into a template, if
/// possible. C++ permits injected-class-names to perform dual service as
/// template template arguments and as template type arguments.
-static TemplateArgumentLoc convertTypeTemplateArgumentToTemplate(TypeLoc TLoc) {
+static TemplateArgumentLoc
+convertTypeTemplateArgumentToTemplate(ASTContext &Context, TypeLoc TLoc) {
// Extract and step over any surrounding nested-name-specifier.
NestedNameSpecifierLoc QualLoc;
if (auto ETLoc = TLoc.getAs<ElaboratedTypeLoc>()) {
@@ -5176,11 +5286,10 @@ static TemplateArgumentLoc convertTypeTemplateArgumentToTemplate(TypeLoc TLoc) {
QualLoc = ETLoc.getQualifierLoc();
TLoc = ETLoc.getNamedTypeLoc();
}
-
// If this type was written as an injected-class-name, it can be used as a
// template template argument.
if (auto InjLoc = TLoc.getAs<InjectedClassNameTypeLoc>())
- return TemplateArgumentLoc(InjLoc.getTypePtr()->getTemplateName(),
+ return TemplateArgumentLoc(Context, InjLoc.getTypePtr()->getTemplateName(),
QualLoc, InjLoc.getNameLoc());
// If this type was written as an injected-class-name, it may have been
@@ -5190,7 +5299,8 @@ static TemplateArgumentLoc convertTypeTemplateArgumentToTemplate(TypeLoc TLoc) {
if (auto RecLoc = TLoc.getAs<RecordTypeLoc>())
if (auto *CTSD =
dyn_cast<ClassTemplateSpecializationDecl>(RecLoc.getDecl()))
- return TemplateArgumentLoc(TemplateName(CTSD->getSpecializedTemplate()),
+ return TemplateArgumentLoc(Context,
+ TemplateName(CTSD->getSpecializedTemplate()),
QualLoc, RecLoc.getNameLoc());
return TemplateArgumentLoc();
@@ -5429,7 +5539,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
// itself.
if (Arg.getArgument().getKind() == TemplateArgument::Type) {
TemplateArgumentLoc ConvertedArg = convertTypeTemplateArgumentToTemplate(
- Arg.getTypeSourceInfo()->getTypeLoc());
+ Context, Arg.getTypeSourceInfo()->getTypeLoc());
if (!ConvertedArg.getArgument().isNull())
Arg = ConvertedArg;
}
@@ -5468,39 +5578,6 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
return false;
}
-/// Check whether the template parameter is a pack expansion, and if so,
-/// determine the number of parameters produced by that expansion. For instance:
-///
-/// \code
-/// template<typename ...Ts> struct A {
-/// template<Ts ...NTs, template<Ts> class ...TTs, typename ...Us> struct B;
-/// };
-/// \endcode
-///
-/// In \c A<int,int>::B, \c NTs and \c TTs have expanded pack size 2, and \c Us
-/// is not a pack expansion, so returns an empty Optional.
-static Optional<unsigned> getExpandedPackSize(NamedDecl *Param) {
- if (TemplateTypeParmDecl *TTP
- = dyn_cast<TemplateTypeParmDecl>(Param)) {
- if (TTP->isExpandedParameterPack())
- return TTP->getNumExpansionParameters();
- }
-
- if (NonTypeTemplateParmDecl *NTTP
- = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
- if (NTTP->isExpandedParameterPack())
- return NTTP->getNumExpansionTypes();
- }
-
- if (TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(Param)) {
- if (TTP->isExpandedParameterPack())
- return TTP->getNumExpansionTemplateParameters();
- }
-
- return None;
-}
-
/// Diagnose a missing template argument.
template<typename TemplateParmDecl>
static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc,
@@ -5748,8 +5825,9 @@ bool Sema::CheckTemplateArgumentList(
if (Name.isNull())
return true;
- Arg = TemplateArgumentLoc(TemplateArgument(Name), QualifierLoc,
- TempParm->getDefaultArgument().getTemplateNameLoc());
+ Arg = TemplateArgumentLoc(
+ Context, TemplateArgument(Name), QualifierLoc,
+ TempParm->getDefaultArgument().getTemplateNameLoc());
}
// Introduce an instantiation record that describes where we are using
@@ -6543,8 +6621,8 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
return true;
// Create the template argument.
- Converted =
- TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()), ParamType);
+ Converted = TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()),
+ S.Context.getCanonicalType(ParamType));
S.MarkAnyDeclReferenced(Arg->getBeginLoc(), Entity, false);
return false;
}
@@ -6665,7 +6743,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
Converted = TemplateArgument(Arg);
} else {
ValueDecl *D = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
- Converted = TemplateArgument(D, ParamType);
+ Converted = TemplateArgument(D, S.Context.getCanonicalType(ParamType));
}
return Invalid;
}
@@ -6691,14 +6769,15 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
SourceLocation StartLoc = Arg->getBeginLoc();
// If the parameter type somehow involves auto, deduce the type now.
- if (getLangOpts().CPlusPlus17 && ParamType->isUndeducedType()) {
+ DeducedType *DeducedT = ParamType->getContainedDeducedType();
+ if (getLangOpts().CPlusPlus17 && DeducedT && !DeducedT->isDeduced()) {
// During template argument deduction, we allow 'decltype(auto)' to
// match an arbitrary dependent argument.
// FIXME: The language rules don't say what happens in this case.
// FIXME: We get an opaque dependent type out of decltype(auto) if the
// expression is merely instantiation-dependent; is this enough?
if (CTAK == CTAK_Deduced && Arg->isTypeDependent()) {
- auto *AT = dyn_cast<AutoType>(ParamType);
+ auto *AT = dyn_cast<AutoType>(DeducedT);
if (AT && AT->isDecltypeAuto()) {
Converted = TemplateArgument(Arg);
return Arg;
@@ -6712,14 +6791,26 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
Expr *DeductionArg = Arg;
if (auto *PE = dyn_cast<PackExpansionExpr>(DeductionArg))
DeductionArg = PE->getPattern();
- if (DeduceAutoType(
- Context.getTrivialTypeSourceInfo(ParamType, Param->getLocation()),
- DeductionArg, ParamType, Depth,
- // We do not check constraints right now because the
- // immediately-declared constraint of the auto type is also an
- // associated constraint, and will be checked along with the other
- // associated constraints after checking the template argument list.
- /*IgnoreConstraints=*/true) == DAR_Failed) {
+ TypeSourceInfo *TSI =
+ Context.getTrivialTypeSourceInfo(ParamType, Param->getLocation());
+ if (isa<DeducedTemplateSpecializationType>(DeducedT)) {
+ InitializedEntity Entity =
+ InitializedEntity::InitializeTemplateParameter(ParamType, Param);
+ InitializationKind Kind = InitializationKind::CreateForInit(
+ DeductionArg->getBeginLoc(), /*DirectInit*/false, DeductionArg);
+ Expr *Inits[1] = {DeductionArg};
+ ParamType =
+ DeduceTemplateSpecializationFromInitializer(TSI, Entity, Kind, Inits);
+ if (ParamType.isNull())
+ return ExprError();
+ } else if (DeduceAutoType(
+ TSI, DeductionArg, ParamType, Depth,
+ // We do not check constraints right now because the
+ // immediately-declared constraint of the auto type is also
+ // an associated constraint, and will be checked along with
+ // the other associated constraints after checking the
+ // template argument list.
+ /*IgnoreConstraints=*/true) == DAR_Failed) {
Diag(Arg->getExprLoc(),
diag::err_non_type_template_parm_type_deduction_failure)
<< Param->getDeclName() << Param->getType() << Arg->getType()
@@ -6742,18 +6833,21 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
assert(!ParamType.hasQualifiers() &&
"non-type template parameter type cannot be qualified");
+ // FIXME: When Param is a reference, should we check that Arg is an lvalue?
if (CTAK == CTAK_Deduced &&
- !Context.hasSameType(ParamType.getNonLValueExprType(Context),
- Arg->getType())) {
+ (ParamType->isReferenceType()
+ ? !Context.hasSameType(ParamType.getNonReferenceType(),
+ Arg->getType())
+ : !Context.hasSameUnqualifiedType(ParamType, Arg->getType()))) {
// FIXME: If either type is dependent, we skip the check. This isn't
// correct, since during deduction we're supposed to have replaced each
// template parameter with some unique (non-dependent) placeholder.
// FIXME: If the argument type contains 'auto', we carry on and fail the
// type check in order to force specific types to be more specialized than
// 'auto'. It's not clear how partial ordering with 'auto' is supposed to
- // work.
+ // work. Similarly for CTAD, when comparing 'A<x>' against 'A'.
if ((ParamType->isDependentType() || Arg->isTypeDependent()) &&
- !Arg->getType()->getContainedAutoType()) {
+ !Arg->getType()->getContainedDeducedType()) {
Converted = TemplateArgument(Arg);
return Arg;
}
@@ -6800,12 +6894,36 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
*this, Sema::ExpressionEvaluationContext::ConstantEvaluated);
if (getLangOpts().CPlusPlus17) {
+ QualType CanonParamType = Context.getCanonicalType(ParamType);
+
+ // Avoid making a copy when initializing a template parameter of class type
+ // from a template parameter object of the same type. This is going beyond
+ // the standard, but is required for soundness: in
+ // template<A a> struct X { X *p; X<a> *q; };
+ // ... we need p and q to have the same type.
+ //
+ // Similarly, don't inject a call to a copy constructor when initializing
+ // from a template parameter of the same type.
+ Expr *InnerArg = Arg->IgnoreParenImpCasts();
+ if (ParamType->isRecordType() && isa<DeclRefExpr>(InnerArg) &&
+ Context.hasSameUnqualifiedType(ParamType, InnerArg->getType())) {
+ NamedDecl *ND = cast<DeclRefExpr>(InnerArg)->getDecl();
+ if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) {
+ Converted = TemplateArgument(TPO, CanonParamType);
+ return Arg;
+ }
+ if (isa<NonTypeTemplateParmDecl>(ND)) {
+ Converted = TemplateArgument(Arg);
+ return Arg;
+ }
+ }
+
// C++17 [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);
+ Arg, ParamType, Value, CCEK_TemplateArg, Param);
if (ArgResult.isInvalid())
return ExprError();
@@ -6816,8 +6934,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
return ArgResult;
}
- QualType CanonParamType = Context.getCanonicalType(ParamType);
-
// Convert the APValue to a TemplateArgument.
switch (Value.getKind()) {
case APValue::None:
@@ -6865,6 +6981,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
return ExprError();
}
// -- a subobject
+ // FIXME: Until C++20
if (Value.hasLValuePath() && Value.getLValuePath().size() == 1 &&
VD && VD->getType()->isArrayType() &&
Value.getLValuePath()[0].getAsArrayIndex() == 0 &&
@@ -6886,6 +7003,13 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
: TemplateArgument(CanonParamType, /*isNullPtr*/true);
break;
}
+ case APValue::Struct:
+ case APValue::Union:
+ // Get or create the corresponding template parameter object.
+ Converted = TemplateArgument(
+ Context.getTemplateParamObjectDecl(CanonParamType, Value),
+ CanonParamType);
+ break;
case APValue::AddrLabelDiff:
return Diag(StartLoc, diag::err_non_type_template_arg_addr_label_diff);
case APValue::FixedPoint:
@@ -6894,9 +7018,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
case APValue::ComplexFloat:
case APValue::Vector:
case APValue::Array:
- case APValue::Struct:
- case APValue::Union:
- llvm_unreachable("invalid kind for template argument");
+ return Diag(StartLoc, diag::err_non_type_template_arg_unsupported)
+ << ParamType;
}
return ArgResult.get();
@@ -6982,14 +7105,13 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
public:
TmplArgICEDiagnoser(QualType T) : T(T) { }
- void diagnoseNotICE(Sema &S, SourceLocation Loc,
- SourceRange SR) override {
- S.Diag(Loc, diag::err_template_arg_not_ice) << T << SR;
+ SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
+ SourceLocation Loc) override {
+ return S.Diag(Loc, diag::err_template_arg_not_ice) << T;
}
} Diagnoser(ArgType);
- Arg = VerifyIntegerConstantExpression(Arg, &Value, Diagnoser,
- false).get();
+ Arg = VerifyIntegerConstantExpression(Arg, &Value, Diagnoser).get();
if (!Arg)
return ExprError();
}
@@ -7389,6 +7511,11 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
RefExpr = CreateBuiltinUnaryOp(Loc, UO_AddrOf, RefExpr.get());
if (RefExpr.isInvalid())
return ExprError();
+ } else if (ParamType->isRecordType()) {
+ assert(isa<TemplateParamObjectDecl>(VD) &&
+ "arg for class template param not a template parameter object");
+ // No conversions apply in this case.
+ return RefExpr;
} else {
assert(ParamType->isReferenceType() &&
"unexpected type for decl template argument");
@@ -7477,7 +7604,7 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
// FIXME: This is a hack. We need a better way to handle substituted
// non-type template parameters.
E = CStyleCastExpr::Create(Context, OrigT, VK_RValue, CK_IntegralCast, E,
- nullptr,
+ nullptr, CurFPFeatureOverrides(),
Context.getTrivialTypeSourceInfo(OrigT, Loc),
Loc, Loc);
}
@@ -7771,22 +7898,28 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {
(S->getFlags() & Scope::TemplateParamScope) != 0)
S = S->getParent();
- // C++ [temp]p4:
- // A template [...] shall not have C linkage.
+ // C++ [temp.pre]p6: [P2096]
+ // A template, explicit specialization, or partial specialization shall not
+ // have C linkage.
DeclContext *Ctx = S->getEntity();
- assert(Ctx && "Unknown context");
- if (Ctx->isExternCContext()) {
+ if (Ctx && Ctx->isExternCContext()) {
Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage)
<< TemplateParams->getSourceRange();
if (const LinkageSpecDecl *LSD = Ctx->getExternCContext())
Diag(LSD->getExternLoc(), diag::note_extern_c_begins_here);
return true;
}
- Ctx = Ctx->getRedeclContext();
+ Ctx = Ctx ? Ctx->getRedeclContext() : nullptr;
// C++ [temp]p2:
// A template-declaration can appear only as a namespace scope or
// class scope declaration.
+ // C++ [temp.expl.spec]p3:
+ // An explicit specialization may be declared in any scope in which the
+ // corresponding primary template may be defined.
+ // C++ [temp.class.spec]p6: [P2096]
+ // A partial specialization may be declared in any scope in which the
+ // corresponding primary template may be defined.
if (Ctx) {
if (Ctx->isFileContext())
return false;
@@ -8106,6 +8239,10 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
if (Invalid)
return true;
+ // Check that we can declare a template specialization here.
+ if (TemplateParams && CheckTemplateDeclScope(S, TemplateParams))
+ return true;
+
if (TemplateParams && TemplateParams->size() > 0) {
isPartialSpecialization = true;
@@ -8198,10 +8335,9 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
// FIXME: Move this to CheckTemplatePartialSpecializationArgs so we
// also do it during instantiation.
- bool InstantiationDependent;
if (!Name.isDependent() &&
- !TemplateSpecializationType::anyDependentTemplateArguments(
- TemplateArgs.arguments(), InstantiationDependent)) {
+ !TemplateSpecializationType::anyDependentTemplateArguments(TemplateArgs,
+ Converted)) {
Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
<< ClassTemplate->getDeclName();
isPartialSpecialization = false;
@@ -8462,6 +8598,9 @@ Decl *Sema::ActOnConceptDefinition(Scope *S,
return nullptr;
}
+ if (DiagnoseUnexpandedParameterPack(ConstraintExpr))
+ return nullptr;
+
ConceptDecl *NewDecl = ConceptDecl::Create(Context, DC, NameLoc, Name,
TemplateParameterLists.front(),
ConstraintExpr);
@@ -9580,11 +9719,11 @@ DeclResult Sema::ActOnExplicitInstantiation(
Def->setTemplateSpecializationKind(TSK);
if (!getDLLAttr(Def) && getDLLAttr(Specialization) &&
- (Context.getTargetInfo().getCXXABI().isMicrosoft() ||
- Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) {
- // In the MS ABI, an explicit instantiation definition can add a dll
- // attribute to a template with a previous instantiation declaration.
- // MinGW doesn't allow this.
+ (Context.getTargetInfo().shouldDLLImportComdatSymbols() &&
+ !Context.getTargetInfo().getTriple().isPS4CPU())) {
+ // An explicit instantiation definition can add a dll attribute to a
+ // template with a previous instantiation declaration. MinGW doesn't
+ // allow this.
auto *A = cast<InheritableAttr>(
getDLLAttr(Specialization)->clone(getASTContext()));
A->setInherited(true);
@@ -9598,19 +9737,19 @@ DeclResult Sema::ActOnExplicitInstantiation(
bool NewlyDLLExported =
!PreviouslyDLLExported && Specialization->hasAttr<DLLExportAttr>();
if (Old_TSK == TSK_ImplicitInstantiation && NewlyDLLExported &&
- (Context.getTargetInfo().getCXXABI().isMicrosoft() ||
- Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) {
- // In the MS ABI, an explicit instantiation definition can add a dll
- // attribute to a template with a previous implicit instantiation.
- // MinGW doesn't allow this. We limit clang to only adding dllexport, to
- // avoid potentially strange codegen behavior. For example, if we extend
- // this conditional to dllimport, and we have a source file calling a
- // method on an implicitly instantiated template class instance and then
- // declaring a dllimport explicit instantiation definition for the same
- // template class, the codegen for the method call will not respect the
- // dllimport, while it will with cl. The Def will already have the DLL
- // attribute, since the Def and Specialization will be the same in the
- // case of Old_TSK == TSK_ImplicitInstantiation, and we already added the
+ (Context.getTargetInfo().shouldDLLImportComdatSymbols() &&
+ !Context.getTargetInfo().getTriple().isPS4CPU())) {
+ // An explicit instantiation definition can add a dll attribute to a
+ // template with a previous implicit instantiation. MinGW doesn't allow
+ // this. We limit clang to only adding dllexport, to avoid potentially
+ // strange codegen behavior. For example, if we extend this conditional
+ // to dllimport, and we have a source file calling a method on an
+ // implicitly instantiated template class instance and then declaring a
+ // dllimport explicit instantiation definition for the same template
+ // class, the codegen for the method call will not respect the dllimport,
+ // while it will with cl. The Def will already have the DLL attribute,
+ // since the Def and Specialization will be the same in the case of
+ // Old_TSK == TSK_ImplicitInstantiation, and we already added the
// attribute to the Specialization; we just need to make it take effect.
assert(Def == Specialization &&
"Def and Specialization should match for implicit instantiation");
@@ -9625,6 +9764,11 @@ DeclResult Sema::ActOnExplicitInstantiation(
dllExportImportClassTemplateSpecialization(*this, Def);
}
+ if (Def->hasAttr<MSInheritanceAttr>()) {
+ Specialization->addAttr(Def->getAttr<MSInheritanceAttr>());
+ Consumer.AssignInheritanceModel(Specialization);
+ }
+
// Set the template specialization kind. Make sure it is set before
// instantiating the members which will trigger ASTConsumer callbacks.
Specialization->setTemplateSpecializationKind(TSK);
@@ -9904,6 +10048,14 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
if (Res.isInvalid())
return true;
+ if (!Res.isUsable()) {
+ // We somehow specified dependent template arguments in an explicit
+ // instantiation. This should probably only happen during error
+ // recovery.
+ Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_dependent);
+ return true;
+ }
+
// Ignore access control bits, we don't need them for redeclaration
// checking.
Prev = cast<VarDecl>(Res.get());
@@ -10583,7 +10735,7 @@ namespace {
/// For the purposes of type reconstruction, a type has already been
/// transformed if it is NULL or if it is not dependent.
bool AlreadyTransformed(QualType T) {
- return T.isNull() || !T->isDependentType();
+ return T.isNull() || !T->isInstantiationDependentType();
}
/// Returns the location of the entity whose type is being
@@ -10636,7 +10788,7 @@ namespace {
TypeSourceInfo *Sema::RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
SourceLocation Loc,
DeclarationName Name) {
- if (!T || !T->getType()->isDependentType())
+ if (!T || !T->getType()->isInstantiationDependentType())
return T;
CurrentInstantiationRebuilder Rebuilder(*this, Loc, Name);
@@ -10926,14 +11078,3 @@ void Sema::checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec) {
ExplicitSpecializationVisibilityChecker(*this, Loc).check(Spec);
}
-
-/// Check whether a template partial specialization that we've discovered
-/// is hidden, and produce suitable diagnostics if so.
-void Sema::checkPartialSpecializationVisibility(SourceLocation Loc,
- NamedDecl *Spec) {
- llvm::SmallVector<Module *, 8> Modules;
- if (!hasVisibleDeclaration(Spec, &Modules))
- diagnoseMissingImport(Loc, Spec, Spec->getLocation(), Modules,
- MissingImportKind::PartialSpecialization,
- /*Recover*/true);
-}
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 5392be57a3aa..ee4316e7a632 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -171,30 +171,41 @@ static void MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
/// If the given expression is of a form that permits the deduction
/// of a non-type template parameter, return the declaration of that
/// non-type template parameter.
-static NonTypeTemplateParmDecl *
-getDeducedParameterFromExpr(TemplateDeductionInfo &Info, Expr *E) {
+static const NonTypeTemplateParmDecl *
+getDeducedParameterFromExpr(const Expr *E, unsigned Depth) {
// If we are within an alias template, the expression may have undergone
// any number of parameter substitutions already.
while (true) {
- if (ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(E))
+ if (const auto *IC = dyn_cast<ImplicitCastExpr>(E))
E = IC->getSubExpr();
- else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(E))
+ else if (const auto *CE = dyn_cast<ConstantExpr>(E))
E = CE->getSubExpr();
- else if (SubstNonTypeTemplateParmExpr *Subst =
- dyn_cast<SubstNonTypeTemplateParmExpr>(E))
+ else if (const auto *Subst = dyn_cast<SubstNonTypeTemplateParmExpr>(E))
E = Subst->getReplacement();
- else
+ else if (const auto *CCE = dyn_cast<CXXConstructExpr>(E)) {
+ // Look through implicit copy construction from an lvalue of the same type.
+ if (CCE->getParenOrBraceRange().isValid())
+ break;
+ // Note, there could be default arguments.
+ assert(CCE->getNumArgs() >= 1 && "implicit construct expr should have 1 arg");
+ E = CCE->getArg(0);
+ } else
break;
}
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
- if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl()))
- if (NTTP->getDepth() == Info.getDeducedDepth())
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
+ if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl()))
+ if (NTTP->getDepth() == Depth)
return NTTP;
return nullptr;
}
+static const NonTypeTemplateParmDecl *
+getDeducedParameterFromExpr(TemplateDeductionInfo &Info, Expr *E) {
+ return getDeducedParameterFromExpr(E, Info.getDeducedDepth());
+}
+
/// Determine whether two declaration pointers refer to the same
/// declaration.
static bool isSameDeclaration(Decl *X, Decl *Y) {
@@ -374,7 +385,7 @@ checkDeducedTemplateArguments(ASTContext &Context,
/// deduction is funneled through here.
static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
Sema &S, TemplateParameterList *TemplateParams,
- NonTypeTemplateParmDecl *NTTP, const DeducedTemplateArgument &NewDeduced,
+ const NonTypeTemplateParmDecl *NTTP, const DeducedTemplateArgument &NewDeduced,
QualType ValueType, TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
assert(NTTP->getDepth() == Info.getDeducedDepth() &&
@@ -383,7 +394,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
DeducedTemplateArgument Result = checkDeducedTemplateArguments(
S.Context, Deduced[NTTP->getIndex()], NewDeduced);
if (Result.isNull()) {
- Info.Param = NTTP;
+ Info.Param = const_cast<NonTypeTemplateParmDecl*>(NTTP);
Info.FirstArg = Deduced[NTTP->getIndex()];
Info.SecondArg = NewDeduced;
return Sema::TDK_Inconsistent;
@@ -410,10 +421,16 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
// type from an argument (of non-reference type) should be performed.
// For now, we just remove reference types from both sides and let
// the final check for matching types sort out the mess.
+ ValueType = ValueType.getNonReferenceType();
+ if (ParamType->isReferenceType())
+ ParamType = ParamType.getNonReferenceType();
+ else
+ // Top-level cv-qualifiers are irrelevant for a non-reference type.
+ ValueType = ValueType.getUnqualifiedType();
+
return DeduceTemplateArgumentsByTypeMatch(
- S, TemplateParams, ParamType.getNonReferenceType(),
- ValueType.getNonReferenceType(), Info, Deduced, TDF_SkipNonDependent,
- /*PartialOrdering=*/false,
+ S, TemplateParams, ParamType, ValueType, Info, Deduced,
+ TDF_SkipNonDependent, /*PartialOrdering=*/false,
/*ArrayBound=*/NewDeduced.wasDeducedFromArrayBound());
}
@@ -421,7 +438,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
/// from the given integral constant.
static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
Sema &S, TemplateParameterList *TemplateParams,
- NonTypeTemplateParmDecl *NTTP, const llvm::APSInt &Value,
+ const NonTypeTemplateParmDecl *NTTP, const llvm::APSInt &Value,
QualType ValueType, bool DeducedFromArrayBound, TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
return DeduceNonTypeTemplateArgument(
@@ -435,7 +452,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
/// from the given null pointer template argument type.
static Sema::TemplateDeductionResult DeduceNullPtrTemplateArgument(
Sema &S, TemplateParameterList *TemplateParams,
- NonTypeTemplateParmDecl *NTTP, QualType NullPtrType,
+ const NonTypeTemplateParmDecl *NTTP, QualType NullPtrType,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
Expr *Value =
@@ -454,7 +471,7 @@ static Sema::TemplateDeductionResult DeduceNullPtrTemplateArgument(
/// \returns true if deduction succeeded, false otherwise.
static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
Sema &S, TemplateParameterList *TemplateParams,
- NonTypeTemplateParmDecl *NTTP, Expr *Value, TemplateDeductionInfo &Info,
+ const NonTypeTemplateParmDecl *NTTP, Expr *Value, TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
DeducedTemplateArgument(Value),
@@ -467,7 +484,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
/// \returns true if deduction succeeded, false otherwise.
static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
Sema &S, TemplateParameterList *TemplateParams,
- NonTypeTemplateParmDecl *NTTP, ValueDecl *D, QualType T,
+ const NonTypeTemplateParmDecl *NTTP, ValueDecl *D, QualType T,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
D = D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
@@ -641,23 +658,6 @@ static TemplateParameter makeTemplateParameter(Decl *D) {
return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
}
-/// If \p Param is an expanded parameter pack, get the number of expansions.
-static Optional<unsigned> getExpandedPackSize(NamedDecl *Param) {
- if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
- if (TTP->isExpandedParameterPack())
- return TTP->getNumExpansionParameters();
-
- if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param))
- if (NTTP->isExpandedParameterPack())
- return NTTP->getNumExpansionTypes();
-
- if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Param))
- if (TTP->isExpandedParameterPack())
- return TTP->getNumExpansionTemplateParameters();
-
- return None;
-}
-
/// A pack that we're currently deducing.
struct clang::DeducedPack {
// The index of the pack.
@@ -1201,6 +1201,120 @@ static bool isForwardingReference(QualType Param, unsigned FirstInnerIndex) {
return false;
}
+/// Attempt to deduce the template arguments by checking the base types
+/// according to (C++20 [temp.deduct.call] p4b3.
+///
+/// \param S the semantic analysis object within which we are deducing.
+///
+/// \param RecordT the top level record object we are deducing against.
+///
+/// \param TemplateParams the template parameters that we are deducing.
+///
+/// \param SpecParam the template specialization parameter type.
+///
+/// \param Info information about the template argument deduction itself.
+///
+/// \param Deduced the deduced template arguments.
+///
+/// \returns the result of template argument deduction with the bases. "invalid"
+/// means no matches, "success" found a single item, and the
+/// "MiscellaneousDeductionFailure" result happens when the match is ambiguous.
+static Sema::TemplateDeductionResult DeduceTemplateBases(
+ Sema &S, const RecordType *RecordT, TemplateParameterList *TemplateParams,
+ const TemplateSpecializationType *SpecParam, TemplateDeductionInfo &Info,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ // C++14 [temp.deduct.call] p4b3:
+ // If P is a class and P has the form simple-template-id, then the
+ // transformed A can be a derived class of the deduced A. Likewise if
+ // P is a pointer to a class of the form simple-template-id, the
+ // transformed A can be a pointer to a derived class pointed to by the
+ // deduced A. However, if there is a class C that is a (direct or
+ // indirect) base class of D and derived (directly or indirectly) from a
+ // class B and that would be a valid deduced A, the deduced A cannot be
+ // B or pointer to B, respectively.
+ //
+ // These alternatives are considered only if type deduction would
+ // otherwise fail. If they yield more than one possible deduced A, the
+ // type deduction fails.
+
+ // Use a breadth-first search through the bases to collect the set of
+ // successful matches. Visited contains the set of nodes we have already
+ // visited, while ToVisit is our stack of records that we still need to
+ // visit. Matches contains a list of matches that have yet to be
+ // disqualified.
+ llvm::SmallPtrSet<const RecordType *, 8> Visited;
+ SmallVector<const RecordType *, 8> ToVisit;
+ // We iterate over this later, so we have to use MapVector to ensure
+ // determinism.
+ llvm::MapVector<const RecordType *, SmallVector<DeducedTemplateArgument, 8>>
+ Matches;
+
+ auto AddBases = [&Visited, &ToVisit](const RecordType *RT) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ for (const auto &Base : RD->bases()) {
+ assert(Base.getType()->isRecordType() &&
+ "Base class that isn't a record?");
+ const RecordType *RT = Base.getType()->getAs<RecordType>();
+ if (Visited.insert(RT).second)
+ ToVisit.push_back(Base.getType()->getAs<RecordType>());
+ }
+ };
+
+ // Set up the loop by adding all the bases.
+ AddBases(RecordT);
+
+ // Search each path of bases until we either run into a successful match
+ // (where all bases of it are invalid), or we run out of bases.
+ while (!ToVisit.empty()) {
+ const RecordType *NextT = ToVisit.pop_back_val();
+
+ SmallVector<DeducedTemplateArgument, 8> DeducedCopy(Deduced.begin(),
+ Deduced.end());
+ TemplateDeductionInfo BaseInfo(TemplateDeductionInfo::ForBase, Info);
+ Sema::TemplateDeductionResult BaseResult =
+ DeduceTemplateArguments(S, TemplateParams, SpecParam,
+ QualType(NextT, 0), BaseInfo, DeducedCopy);
+
+ // If this was a successful deduction, add it to the list of matches,
+ // otherwise we need to continue searching its bases.
+ if (BaseResult == Sema::TDK_Success)
+ Matches.insert({NextT, DeducedCopy});
+ else
+ AddBases(NextT);
+ }
+
+ // At this point, 'Matches' contains a list of seemingly valid bases, however
+ // in the event that we have more than 1 match, it is possible that the base
+ // of one of the matches might be disqualified for being a base of another
+ // valid match. We can count on cyclical instantiations being invalid to
+ // simplify the disqualifications. That is, if A & B are both matches, and B
+ // inherits from A (disqualifying A), we know that A cannot inherit from B.
+ if (Matches.size() > 1) {
+ Visited.clear();
+ for (const auto &Match : Matches)
+ AddBases(Match.first);
+
+ // We can give up once we have a single item (or have run out of things to
+ // search) since cyclical inheritence isn't valid.
+ while (Matches.size() > 1 && !ToVisit.empty()) {
+ const RecordType *NextT = ToVisit.pop_back_val();
+ Matches.erase(NextT);
+
+ // Always add all bases, since the inheritence tree can contain
+ // disqualifications for multiple matches.
+ AddBases(NextT);
+ }
+ }
+
+ if (Matches.empty())
+ return Sema::TDK_Invalid;
+ if (Matches.size() > 1)
+ return Sema::TDK_MiscellaneousDeductionFailure;
+
+ std::swap(Matches.front().second, Deduced);
+ return Sema::TDK_Success;
+}
+
/// Deduce the template arguments by comparing the parameter type and
/// the argument type (C++ [temp.deduct.type]).
///
@@ -1484,14 +1598,18 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Sema::TDK_Success;
}
} else if (!Param->isDependentType()) {
- CanQualType ParamUnqualType = CanParam.getUnqualifiedType(),
- ArgUnqualType = CanArg.getUnqualifiedType();
- bool Success =
- (TDF & TDF_AllowCompatibleFunctionType)
- ? S.isSameOrCompatibleFunctionType(ParamUnqualType, ArgUnqualType)
- : ParamUnqualType == ArgUnqualType;
- if (Success)
+ if (!(TDF & TDF_SkipNonDependent)) {
+ CanQualType ParamUnqualType = CanParam.getUnqualifiedType(),
+ ArgUnqualType = CanArg.getUnqualifiedType();
+ bool Success =
+ (TDF & TDF_AllowCompatibleFunctionType)
+ ? S.isSameOrCompatibleFunctionType(ParamUnqualType, ArgUnqualType)
+ : ParamUnqualType == ArgUnqualType;
+ if (Success)
+ return Sema::TDK_Success;
+ } else {
return Sema::TDK_Success;
+ }
}
switch (Param->getTypeClass()) {
@@ -1643,7 +1761,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Result;
// Determine the array bound is something we can deduce.
- NonTypeTemplateParmDecl *NTTP
+ const NonTypeTemplateParmDecl *NTTP
= getDeducedParameterFromExpr(Info, DependentArrayParm->getSizeExpr());
if (!NTTP)
return Sema::TDK_Success;
@@ -1712,7 +1830,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
// deducing through the noexcept-specifier if it's part of the canonical
// type. libstdc++ relies on this.
Expr *NoexceptExpr = FunctionProtoParam->getNoexceptExpr();
- if (NonTypeTemplateParmDecl *NTTP =
+ if (const NonTypeTemplateParmDecl *NTTP =
NoexceptExpr ? getDeducedParameterFromExpr(Info, NoexceptExpr)
: nullptr) {
assert(NTTP->getDepth() == Info.getDeducedDepth() &&
@@ -1787,78 +1905,15 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
if (!S.isCompleteType(Info.getLocation(), Arg))
return Result;
- // C++14 [temp.deduct.call] p4b3:
- // If P is a class and P has the form simple-template-id, then the
- // transformed A can be a derived class of the deduced A. Likewise if
- // P is a pointer to a class of the form simple-template-id, the
- // transformed A can be a pointer to a derived class pointed to by the
- // deduced A.
- //
- // These alternatives are considered only if type deduction would
- // otherwise fail. If they yield more than one possible deduced A, the
- // type deduction fails.
-
// Reset the incorrectly deduced argument from above.
Deduced = DeducedOrig;
- // Use data recursion to crawl through the list of base classes.
- // Visited contains the set of nodes we have already visited, while
- // ToVisit is our stack of records that we still need to visit.
- llvm::SmallPtrSet<const RecordType *, 8> Visited;
- SmallVector<const RecordType *, 8> ToVisit;
- ToVisit.push_back(RecordT);
- bool Successful = false;
- SmallVector<DeducedTemplateArgument, 8> SuccessfulDeduced;
- while (!ToVisit.empty()) {
- // Retrieve the next class in the inheritance hierarchy.
- const RecordType *NextT = ToVisit.pop_back_val();
-
- // If we have already seen this type, skip it.
- if (!Visited.insert(NextT).second)
- continue;
-
- // If this is a base class, try to perform template argument
- // deduction from it.
- if (NextT != RecordT) {
- TemplateDeductionInfo BaseInfo(TemplateDeductionInfo::ForBase, Info);
- Sema::TemplateDeductionResult BaseResult =
- DeduceTemplateArguments(S, TemplateParams, SpecParam,
- QualType(NextT, 0), BaseInfo, Deduced);
-
- // If template argument deduction for this base was successful,
- // note that we had some success. Otherwise, ignore any deductions
- // from this base class.
- if (BaseResult == Sema::TDK_Success) {
- // If we've already seen some success, then deduction fails due to
- // an ambiguity (temp.deduct.call p5).
- if (Successful)
- return Sema::TDK_MiscellaneousDeductionFailure;
-
- Successful = true;
- std::swap(SuccessfulDeduced, Deduced);
-
- Info.Param = BaseInfo.Param;
- Info.FirstArg = BaseInfo.FirstArg;
- Info.SecondArg = BaseInfo.SecondArg;
- }
-
- Deduced = DeducedOrig;
- }
-
- // Visit base classes
- CXXRecordDecl *Next = cast<CXXRecordDecl>(NextT->getDecl());
- for (const auto &Base : Next->bases()) {
- assert(Base.getType()->isRecordType() &&
- "Base class that isn't a record?");
- ToVisit.push_back(Base.getType()->getAs<RecordType>());
- }
- }
-
- if (Successful) {
- std::swap(SuccessfulDeduced, Deduced);
- return Sema::TDK_Success;
- }
+ // Check bases according to C++14 [temp.deduct.call] p4b3:
+ Sema::TemplateDeductionResult BaseResult = DeduceTemplateBases(
+ S, RecordT, TemplateParams, SpecParam, Info, Deduced);
+ if (BaseResult != Sema::TDK_Invalid)
+ return BaseResult;
return Result;
}
@@ -1964,7 +2019,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Result;
// Perform deduction on the vector size, if we can.
- NonTypeTemplateParmDecl *NTTP =
+ const NonTypeTemplateParmDecl *NTTP =
getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr());
if (!NTTP)
return Sema::TDK_Success;
@@ -1988,7 +2043,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Result;
// Perform deduction on the vector size, if we can.
- NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(
+ const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(
Info, VectorParam->getSizeExpr());
if (!NTTP)
return Sema::TDK_Success;
@@ -2017,8 +2072,8 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Result;
// Perform deduction on the vector size, if we can.
- NonTypeTemplateParmDecl *NTTP
- = getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr());
+ const NonTypeTemplateParmDecl *NTTP =
+ getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr());
if (!NTTP)
return Sema::TDK_Success;
@@ -2043,8 +2098,8 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Result;
// Perform deduction on the vector size, if we can.
- NonTypeTemplateParmDecl *NTTP
- = getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr());
+ const NonTypeTemplateParmDecl *NTTP =
+ getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr());
if (!NTTP)
return Sema::TDK_Success;
@@ -2100,28 +2155,27 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
const auto *ArgConstMatrix = dyn_cast<ConstantMatrixType>(Arg);
const auto *ArgDepMatrix = dyn_cast<DependentSizedMatrixType>(Arg);
if (!ParamExpr->isValueDependent()) {
- llvm::APSInt ParamConst(
- S.Context.getTypeSize(S.Context.getSizeType()));
- if (!ParamExpr->isIntegerConstantExpr(ParamConst, S.Context))
+ Optional<llvm::APSInt> ParamConst =
+ ParamExpr->getIntegerConstantExpr(S.Context);
+ if (!ParamConst)
return Sema::TDK_NonDeducedMismatch;
if (ArgConstMatrix) {
- if ((ArgConstMatrix->*GetArgDimension)() == ParamConst)
+ if ((ArgConstMatrix->*GetArgDimension)() == *ParamConst)
return Sema::TDK_Success;
return Sema::TDK_NonDeducedMismatch;
}
Expr *ArgExpr = (ArgDepMatrix->*GetArgDimensionExpr)();
- llvm::APSInt ArgConst(
- S.Context.getTypeSize(S.Context.getSizeType()));
- if (!ArgExpr->isValueDependent() &&
- ArgExpr->isIntegerConstantExpr(ArgConst, S.Context) &&
- ArgConst == ParamConst)
- return Sema::TDK_Success;
+ if (!ArgExpr->isValueDependent())
+ if (Optional<llvm::APSInt> ArgConst =
+ ArgExpr->getIntegerConstantExpr(S.Context))
+ if (*ArgConst == *ParamConst)
+ return Sema::TDK_Success;
return Sema::TDK_NonDeducedMismatch;
}
- NonTypeTemplateParmDecl *NTTP =
+ const NonTypeTemplateParmDecl *NTTP =
getDeducedParameterFromExpr(Info, ParamExpr);
if (!NTTP)
return Sema::TDK_Success;
@@ -2168,7 +2222,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Result;
// Perform deduction on the address space, if we can.
- NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(
+ const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(
Info, AddressSpaceParam->getAddrSpaceExpr());
if (!NTTP)
return Sema::TDK_Success;
@@ -2191,7 +2245,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Result;
// Perform deduction on the address space, if we can.
- NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(
+ const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(
Info, AddressSpaceParam->getAddrSpaceExpr());
if (!NTTP)
return Sema::TDK_Success;
@@ -2210,7 +2264,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
if (IntParam->isUnsigned() != IntArg->isUnsigned())
return Sema::TDK_NonDeducedMismatch;
- NonTypeTemplateParmDecl *NTTP =
+ const NonTypeTemplateParmDecl *NTTP =
getDeducedParameterFromExpr(Info, IntParam->getNumBitsExpr());
if (!NTTP)
return Sema::TDK_Success;
@@ -2327,8 +2381,8 @@ DeduceTemplateArguments(Sema &S,
return Sema::TDK_NonDeducedMismatch;
case TemplateArgument::Expression:
- if (NonTypeTemplateParmDecl *NTTP
- = getDeducedParameterFromExpr(Info, Param.getAsExpr())) {
+ if (const NonTypeTemplateParmDecl *NTTP =
+ getDeducedParameterFromExpr(Info, Param.getAsExpr())) {
if (Arg.getKind() == TemplateArgument::Integral)
return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
Arg.getAsIntegral(),
@@ -2620,11 +2674,11 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
if (Arg.getKind() == TemplateArgument::Template)
- return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(Context),
- Loc);
+ return TemplateArgumentLoc(Context, Arg,
+ Builder.getWithLocInContext(Context), Loc);
- return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(Context),
- Loc, Loc);
+ return TemplateArgumentLoc(
+ Context, Arg, Builder.getWithLocInContext(Context), Loc, Loc);
}
case TemplateArgument::Expression:
@@ -3807,17 +3861,18 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(
if (ParamRefType) {
// If the argument has incomplete array type, try to complete its type.
- if (ArgType->isIncompleteArrayType()) {
- S.completeExprArrayBound(Arg);
- ArgType = Arg->getType();
- }
+ if (ArgType->isIncompleteArrayType())
+ ArgType = S.getCompletedType(Arg);
// C++1z [temp.deduct.call]p3:
// If P is a forwarding reference and the argument is an lvalue, the type
// "lvalue reference to A" is used in place of A for type deduction.
if (isForwardingReference(QualType(ParamRefType, 0), FirstInnerIndex) &&
- Arg->isLValue())
+ Arg->isLValue()) {
+ if (S.getLangOpts().OpenCL)
+ ArgType = S.Context.getAddrSpaceQualType(ArgType, LangAS::opencl_generic);
ArgType = S.Context.getLValueReferenceType(ArgType);
+ }
} else {
// C++ [temp.deduct.call]p2:
// If P is not a reference type:
@@ -3929,7 +3984,7 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList(
// from the length of the initializer list.
if (auto *DependentArrTy = dyn_cast_or_null<DependentSizedArrayType>(ArrTy)) {
// Determine the array bound is something we can deduce.
- if (NonTypeTemplateParmDecl *NTTP =
+ if (const NonTypeTemplateParmDecl *NTTP =
getDeducedParameterFromExpr(Info, DependentArrTy->getSizeExpr())) {
// We can perform template argument deduction for the given non-type
// template parameter.
@@ -4894,6 +4949,13 @@ QualType Sema::ReplaceAutoType(QualType TypeWithAuto,
.TransformType(TypeWithAuto);
}
+TypeSourceInfo *Sema::ReplaceAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
+ QualType TypeToReplaceAuto) {
+ return SubstituteDeducedTypeTransform(*this, TypeToReplaceAuto,
+ /*UseTypeSugar*/ false)
+ .TransformType(TypeWithAuto);
+}
+
void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
if (isa<InitListExpr>(Init))
Diag(VDecl->getLocation(),
@@ -4941,8 +5003,12 @@ bool Sema::DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
"failed to deduce lambda return type");
// Build the new return type from scratch.
+ CallingConv RetTyCC = FD->getReturnType()
+ ->getPointeeType()
+ ->castAs<FunctionType>()
+ ->getCallConv();
QualType RetType = getLambdaConversionFunctionResultType(
- CallOp->getType()->castAs<FunctionProtoType>());
+ CallOp->getType()->castAs<FunctionProtoType>(), RetTyCC);
if (FD->getReturnType()->getAs<PointerType>())
RetType = Context.getPointerType(RetType);
else {
@@ -5668,26 +5734,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
if (const PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(E))
E = Expansion->getPattern();
- // Skip through any implicit casts we added while type-checking, and any
- // substitutions performed by template alias expansion.
- while (true) {
- if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
- E = ICE->getSubExpr();
- else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(E))
- E = CE->getSubExpr();
- else if (const SubstNonTypeTemplateParmExpr *Subst =
- dyn_cast<SubstNonTypeTemplateParmExpr>(E))
- E = Subst->getReplacement();
- else
- break;
- }
-
- const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
- if (!DRE)
- return;
-
- const NonTypeTemplateParmDecl *NTTP
- = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
+ const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(E, Depth);
if (!NTTP)
return;
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 11e03c517d01..8bd812b39de4 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -141,7 +141,12 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
TSK_ExplicitSpecialization)
break;
- if (const TemplateArgumentList *TemplateArgs
+ if (!RelativeToPrimary && Function->getTemplateSpecializationKind() ==
+ TSK_ExplicitSpecialization) {
+ // This is an implicit instantiation of an explicit specialization. We
+ // don't get any template arguments from this function but might get
+ // some from an enclosing template.
+ } else if (const TemplateArgumentList *TemplateArgs
= Function->getTemplateSpecializationArgs()) {
// Add the template arguments for this specialization.
Result.addOuterTemplateArguments(TemplateArgs);
@@ -237,7 +242,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
// error have occurred. Any diagnostics we might have raised will not be
// visible, and we do not need to construct a correct AST.
if (SemaRef.Diags.hasFatalErrorOccurred() &&
- SemaRef.Diags.hasUncompilableErrorOccurred()) {
+ SemaRef.hasUncompilableErrorOccurred()) {
Invalid = true;
return;
}
@@ -256,7 +261,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
AlreadyInstantiating = !Inst.Entity ? false :
!SemaRef.InstantiatingSpecializations
- .insert(std::make_pair(Inst.Entity->getCanonicalDecl(), Inst.Kind))
+ .insert({Inst.Entity->getCanonicalDecl(), Inst.Kind})
.second;
atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, Inst);
}
@@ -475,7 +480,7 @@ void Sema::InstantiatingTemplate::Clear() {
auto &Active = SemaRef.CodeSynthesisContexts.back();
if (Active.Entity)
SemaRef.InstantiatingSpecializations.erase(
- std::make_pair(Active.Entity, Active.Kind));
+ {Active.Entity->getCanonicalDecl(), Active.Kind});
}
atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef,
@@ -579,7 +584,7 @@ void Sema::PrintInstantiationStack() {
case CodeSynthesisContext::DefaultTemplateArgumentInstantiation: {
TemplateDecl *Template = cast<TemplateDecl>(Active->Template);
- SmallVector<char, 128> TemplateArgsStr;
+ SmallString<128> TemplateArgsStr;
llvm::raw_svector_ostream OS(TemplateArgsStr);
Template->printName(OS);
printTemplateArgumentList(OS, Active->template_arguments(),
@@ -645,7 +650,7 @@ void Sema::PrintInstantiationStack() {
ParmVarDecl *Param = cast<ParmVarDecl>(Active->Entity);
FunctionDecl *FD = cast<FunctionDecl>(Param->getDeclContext());
- SmallVector<char, 128> TemplateArgsStr;
+ SmallString<128> TemplateArgsStr;
llvm::raw_svector_ostream OS(TemplateArgsStr);
FD->printName(OS);
printTemplateArgumentList(OS, Active->template_arguments(),
@@ -797,7 +802,7 @@ void Sema::PrintInstantiationStack() {
assert(isa<FunctionDecl>(Active->Entity));
DiagID = diag::note_checking_constraints_for_function_here;
}
- SmallVector<char, 128> TemplateArgsStr;
+ SmallString<128> TemplateArgsStr;
llvm::raw_svector_ostream OS(TemplateArgsStr);
cast<NamedDecl>(Active->Entity)->printName(OS);
if (!isa<FunctionDecl>(Active->Entity))
@@ -856,6 +861,7 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
case CodeSynthesisContext::DefaultTemplateArgumentInstantiation:
case CodeSynthesisContext::PriorTemplateArgumentSubstitution:
case CodeSynthesisContext::DefaultTemplateArgumentChecking:
+ case CodeSynthesisContext::RewritingOperatorAsSpaceship:
// A default template argument instantiation and substitution into
// template parameters with arguments for prior parameters may or may
// not be a SFINAE context; look further up the stack.
@@ -874,7 +880,6 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
case CodeSynthesisContext::DeclaringSpecialMember:
case CodeSynthesisContext::DeclaringImplicitEqualityComparison:
case CodeSynthesisContext::DefiningSynthesizedFunction:
- case CodeSynthesisContext::RewritingOperatorAsSpaceship:
case CodeSynthesisContext::InitializingStructuredBinding:
case CodeSynthesisContext::MarkingClassDllexported:
// This happens in a context unrelated to template instantiation, so
@@ -1414,47 +1419,11 @@ TemplateName TemplateInstantiator::TransformTemplateName(
AllowInjectedClassName);
}
-static ExprResult TransformUniqueStableName(TemplateInstantiator &TI,
- PredefinedExpr *E) {
- if (E->getIdentKind() == PredefinedExpr::UniqueStableNameType) {
- TypeSourceInfo *Info =
- TI.getDerived().TransformType(E->getTypeSourceInfo());
-
- if (!Info)
- return ExprError();
-
- if (!TI.getDerived().AlwaysRebuild() && Info == E->getTypeSourceInfo())
- return E;
-
- return TI.getSema().BuildUniqueStableName(E->getLocation(), Info);
- }
-
- if (E->getIdentKind() == PredefinedExpr::UniqueStableNameExpr) {
- EnterExpressionEvaluationContext Unevaluated(
- TI.getSema(), Sema::ExpressionEvaluationContext::Unevaluated);
- ExprResult SubExpr = TI.getDerived().TransformExpr(E->getExpr());
-
- if (SubExpr.isInvalid())
- return ExprError();
-
- if (!TI.getDerived().AlwaysRebuild() && SubExpr.get() == E->getExpr())
- return E;
-
- return TI.getSema().BuildUniqueStableName(E->getLocation(), SubExpr.get());
- }
-
- llvm_unreachable("Only valid for UniqueStableNameType/Expr");
-}
-
ExprResult
TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
if (!E->isTypeDependent())
return E;
- if (E->getIdentKind() == PredefinedExpr::UniqueStableNameType ||
- E->getIdentKind() == PredefinedExpr::UniqueStableNameExpr)
- return TransformUniqueStableName(*this, E);
-
return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentKind());
}
@@ -1500,9 +1469,12 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
if (TargetType.isNull())
return ExprError();
+ QualType ExprType = TargetType.getNonLValueExprType(SemaRef.Context);
+ if (TargetType->isRecordType())
+ ExprType.addConst();
+
return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr(
- TargetType.getNonLValueExprType(SemaRef.Context),
- TargetType->isReferenceType() ? VK_LValue : VK_RValue, NTTP,
+ ExprType, TargetType->isReferenceType() ? VK_LValue : VK_RValue, NTTP,
E->getLocation(), Arg);
}
@@ -1534,15 +1506,39 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
SourceLocation loc,
TemplateArgument arg) {
ExprResult result;
- QualType type;
- // The template argument itself might be an expression, in which
- // case we just return that expression.
+ // Determine the substituted parameter type. We can usually infer this from
+ // the template argument, but not always.
+ auto SubstParamType = [&] {
+ QualType T;
+ if (parm->isExpandedParameterPack())
+ T = parm->getExpansionType(SemaRef.ArgumentPackSubstitutionIndex);
+ else
+ T = parm->getType();
+ if (parm->isParameterPack() && isa<PackExpansionType>(T))
+ T = cast<PackExpansionType>(T)->getPattern();
+ return SemaRef.SubstType(T, TemplateArgs, loc, parm->getDeclName());
+ };
+
+ bool refParam = false;
+
+ // The template argument itself might be an expression, in which case we just
+ // return that expression. This happens when substituting into an alias
+ // template.
if (arg.getKind() == TemplateArgument::Expression) {
Expr *argExpr = arg.getAsExpr();
result = argExpr;
- type = argExpr->getType();
-
+ if (argExpr->isLValue()) {
+ if (argExpr->getType()->isRecordType()) {
+ // Check whether the parameter was actually a reference.
+ QualType paramType = SubstParamType();
+ if (paramType.isNull())
+ return ExprError();
+ refParam = paramType->isReferenceType();
+ } else {
+ refParam = true;
+ }
+ }
} else if (arg.getKind() == TemplateArgument::Declaration ||
arg.getKind() == TemplateArgument::NullPtr) {
ValueDecl *VD;
@@ -1560,36 +1556,25 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
VD = nullptr;
}
- // Derive the type we want the substituted decl to have. This had
- // better be non-dependent, or these checks will have serious problems.
- if (parm->isExpandedParameterPack()) {
- type = parm->getExpansionType(SemaRef.ArgumentPackSubstitutionIndex);
- } else if (parm->isParameterPack() &&
- isa<PackExpansionType>(parm->getType())) {
- type = SemaRef.SubstType(
- cast<PackExpansionType>(parm->getType())->getPattern(),
- TemplateArgs, loc, parm->getDeclName());
- } else {
- type = SemaRef.SubstType(VD ? arg.getParamTypeForDecl() : arg.getNullPtrType(),
- TemplateArgs, loc, parm->getDeclName());
- }
- assert(!type.isNull() && "type substitution failed for param type");
- assert(!type->isDependentType() && "param type still dependent");
- result = SemaRef.BuildExpressionFromDeclTemplateArgument(arg, type, loc);
-
- if (!result.isInvalid()) type = result.get()->getType();
+ QualType paramType = VD ? arg.getParamTypeForDecl() : arg.getNullPtrType();
+ assert(!paramType.isNull() && "type substitution failed for param type");
+ assert(!paramType->isDependentType() && "param type still dependent");
+ result = SemaRef.BuildExpressionFromDeclTemplateArgument(arg, paramType, loc);
+ refParam = paramType->isReferenceType();
} else {
result = SemaRef.BuildExpressionFromIntegralTemplateArgument(arg, loc);
-
- // Note that this type can be different from the type of 'result',
- // e.g. if it's an enum type.
- type = arg.getIntegralType();
+ assert(result.isInvalid() ||
+ SemaRef.Context.hasSameType(result.get()->getType(),
+ arg.getIntegralType()));
}
- if (result.isInvalid()) return ExprError();
+
+ if (result.isInvalid())
+ return ExprError();
Expr *resultExpr = result.get();
return new (SemaRef.Context) SubstNonTypeTemplateParmExpr(
- type, resultExpr->getValueKind(), loc, parm, resultExpr);
+ resultExpr->getType(), resultExpr->getValueKind(), loc, parm, refParam,
+ resultExpr);
}
ExprResult
@@ -1610,10 +1595,12 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
ExprResult
TemplateInstantiator::TransformSubstNonTypeTemplateParmExpr(
SubstNonTypeTemplateParmExpr *E) {
- ExprResult SubstReplacement = TransformExpr(E->getReplacement());
+ ExprResult SubstReplacement = E->getReplacement();
+ if (!isa<ConstantExpr>(SubstReplacement.get()))
+ SubstReplacement = TransformExpr(E->getReplacement());
if (SubstReplacement.isInvalid())
return true;
- QualType SubstType = TransformType(E->getType());
+ QualType SubstType = TransformType(E->getParameterType(getSema().Context));
if (SubstType.isNull())
return true;
// The type may have been previously dependent and not now, which means we
@@ -2732,7 +2719,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
// BlockDecls can appear in a default-member-initializer. They must be the
// child of a BlockExpr, so we only know how to instantiate them from there.
- if (isa<BlockDecl>(Member))
+ // Similarly, lambda closure types are recreated when instantiating the
+ // corresponding LambdaExpr.
+ if (isa<BlockDecl>(Member) ||
+ (isa<CXXRecordDecl>(Member) && cast<CXXRecordDecl>(Member)->isLambda()))
continue;
if (Member->isInvalidDecl()) {
@@ -2806,7 +2796,8 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
Attr *NewAttr =
instantiateTemplateAttribute(I->TmplAttr, Context, *this, TemplateArgs);
- I->NewDecl->addAttr(NewAttr);
+ if (NewAttr)
+ I->NewDecl->addAttr(NewAttr);
LocalInstantiationScope::deleteScopes(I->Scope,
Instantiator.getStartingScope());
}
@@ -2858,8 +2849,6 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
SavedContext.pop();
if (!Instantiation->isInvalidDecl()) {
- Consumer.HandleTagDeclDefinition(Instantiation);
-
// Always emit the vtable for an explicit instantiation definition
// of a polymorphic class template specialization. Otherwise, eagerly
// instantiate only constexpr virtual functions in preparation for their use
@@ -2871,6 +2860,8 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
/*ConstexprOnly*/ true);
}
+ Consumer.HandleTagDeclDefinition(Instantiation);
+
return Instantiation->isInvalidDecl();
}
@@ -2972,9 +2963,10 @@ bool Sema::InstantiateInClassInitializer(
RecordDecl *PatternRD = Pattern->getParent();
RecordDecl *OutermostClass = PatternRD->getOuterLexicalRecordContext();
Diag(PointOfInstantiation,
- diag::err_in_class_initializer_not_yet_parsed)
+ diag::err_default_member_initializer_not_yet_parsed)
<< OutermostClass << Pattern;
- Diag(Pattern->getEndLoc(), diag::note_in_class_initializer_not_yet_parsed);
+ Diag(Pattern->getEndLoc(),
+ diag::note_default_member_initializer_not_yet_parsed);
Instantiation->setInvalidDecl();
return true;
}
@@ -2984,7 +2976,7 @@ bool Sema::InstantiateInClassInitializer(
return true;
if (Inst.isAlreadyInstantiating()) {
// Error out if we hit an instantiation cycle for this initializer.
- Diag(PointOfInstantiation, diag::err_in_class_initializer_cycle)
+ Diag(PointOfInstantiation, diag::err_default_member_initializer_cycle)
<< Instantiation;
return true;
}
@@ -3048,14 +3040,16 @@ bool Sema::usesPartialOrExplicitSpecialization(
/// Get the instantiation pattern to use to instantiate the definition of a
/// given ClassTemplateSpecializationDecl (either the pattern of the primary
/// template or of a partial specialization).
-static CXXRecordDecl *
+static ActionResult<CXXRecordDecl *>
getPatternForClassTemplateSpecialization(
Sema &S, SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
- TemplateSpecializationKind TSK, bool Complain) {
+ TemplateSpecializationKind TSK) {
Sema::InstantiatingTemplate Inst(S, PointOfInstantiation, ClassTemplateSpec);
- if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
- return nullptr;
+ if (Inst.isInvalid())
+ return {/*Invalid=*/true};
+ if (Inst.isAlreadyInstantiating())
+ return {/*Invalid=*/false};
llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *>
@@ -3152,7 +3146,7 @@ getPatternForClassTemplateSpecialization(
<< S.getTemplateArgumentBindingsText(
P->Partial->getTemplateParameters(), *P->Args);
- return nullptr;
+ return {/*Invalid=*/true};
}
}
@@ -3203,14 +3197,15 @@ bool Sema::InstantiateClassTemplateSpecialization(
if (ClassTemplateSpec->isInvalidDecl())
return true;
- CXXRecordDecl *Pattern = getPatternForClassTemplateSpecialization(
- *this, PointOfInstantiation, ClassTemplateSpec, TSK, Complain);
- if (!Pattern)
- return true;
+ ActionResult<CXXRecordDecl *> Pattern =
+ getPatternForClassTemplateSpecialization(*this, PointOfInstantiation,
+ ClassTemplateSpec, TSK);
+ if (!Pattern.isUsable())
+ return Pattern.isInvalid();
- return InstantiateClass(PointOfInstantiation, ClassTemplateSpec, Pattern,
- getTemplateInstantiationArgs(ClassTemplateSpec), TSK,
- Complain);
+ return InstantiateClass(
+ PointOfInstantiation, ClassTemplateSpec, Pattern.get(),
+ getTemplateInstantiationArgs(ClassTemplateSpec), TSK, Complain);
}
/// Instantiates the definitions of all of the member
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 2efb7acb9724..dc1e0ef60cac 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -181,6 +181,22 @@ static void instantiateDependentAllocAlignAttr(
S.AddAllocAlignAttr(New, *Align, Param);
}
+static void instantiateDependentAnnotationAttr(
+ Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
+ const AnnotateAttr *Attr, Decl *New) {
+ EnterExpressionEvaluationContext Unevaluated(
+ S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+ SmallVector<Expr *, 4> Args;
+ Args.reserve(Attr->args_size());
+ for (auto *E : Attr->args()) {
+ ExprResult Result = S.SubstExpr(E, TemplateArgs);
+ if (!Result.isUsable())
+ return;
+ Args.push_back(Result.get());
+ }
+ S.AddAnnotationAttr(New, *Attr, Attr->getAnnotation(), Args);
+}
+
static Expr *instantiateDependentFunctionAttrCondition(
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
const Attr *A, Expr *OldCond, const Decl *Tmpl, FunctionDecl *New) {
@@ -417,7 +433,9 @@ static void instantiateOMPDeclareVariantAttr(
if (TI.anyScoreOrCondition(SubstScoreOrConditionExpr))
return;
- // Check function/variant ref.
+ Expr *E = VariantFuncRef.get();
+ // Check function/variant ref for `omp declare variant` but not for `omp
+ // begin declare variant` (which use implicit attributes).
Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
S.checkOpenMPDeclareVariantFunction(S.ConvertDeclToDeclGroup(New),
VariantFuncRef.get(), TI,
@@ -426,9 +444,42 @@ static void instantiateOMPDeclareVariantAttr(
if (!DeclVarData)
return;
- S.ActOnOpenMPDeclareVariantDirective(DeclVarData.getValue().first,
- DeclVarData.getValue().second, TI,
- Attr.getRange());
+ E = DeclVarData.getValue().second;
+ FD = DeclVarData.getValue().first;
+
+ if (auto *VariantDRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) {
+ if (auto *VariantFD = dyn_cast<FunctionDecl>(VariantDRE->getDecl())) {
+ if (auto *VariantFTD = VariantFD->getDescribedFunctionTemplate()) {
+ if (!VariantFTD->isThisDeclarationADefinition())
+ return;
+ Sema::TentativeAnalysisScope Trap(S);
+ const TemplateArgumentList *TAL = TemplateArgumentList::CreateCopy(
+ S.Context, TemplateArgs.getInnermost());
+
+ auto *SubstFD = S.InstantiateFunctionDeclaration(VariantFTD, TAL,
+ New->getLocation());
+ if (!SubstFD)
+ return;
+ QualType NewType = S.Context.mergeFunctionTypes(
+ SubstFD->getType(), FD->getType(),
+ /* OfBlockPointer */ false,
+ /* Unqualified */ false, /* AllowCXX */ true);
+ if (NewType.isNull())
+ return;
+ S.InstantiateFunctionDefinition(
+ New->getLocation(), SubstFD, /* Recursive */ true,
+ /* DefinitionRequired */ false, /* AtEndOfTU */ false);
+ SubstFD->setInstantiationIsPending(!SubstFD->isDefined());
+ E = DeclRefExpr::Create(S.Context, NestedNameSpecifierLoc(),
+ SourceLocation(), SubstFD,
+ /* RefersToEnclosingVariableOrCapture */ false,
+ /* NameLoc */ SubstFD->getLocation(),
+ SubstFD->getType(), ExprValueKind::VK_RValue);
+ }
+ }
+ }
+
+ S.ActOnOpenMPDeclareVariantDirective(FD, E, TI, Attr.getRange());
}
static void instantiateDependentAMDGPUFlatWorkGroupSizeAttr(
@@ -497,12 +548,40 @@ static void instantiateDependentAMDGPUWavesPerEUAttr(
S.addAMDGPUWavesPerEUAttr(New, Attr, MinExpr, MaxExpr);
}
+/// Determine whether the attribute A might be relevent to the declaration D.
+/// If not, we can skip instantiating it. The attribute may or may not have
+/// been instantiated yet.
+static bool isRelevantAttr(Sema &S, const Decl *D, const Attr *A) {
+ // 'preferred_name' is only relevant to the matching specialization of the
+ // template.
+ if (const auto *PNA = dyn_cast<PreferredNameAttr>(A)) {
+ QualType T = PNA->getTypedefType();
+ const auto *RD = cast<CXXRecordDecl>(D);
+ if (!T->isDependentType() && !RD->isDependentContext() &&
+ !declaresSameEntity(T->getAsCXXRecordDecl(), RD))
+ return false;
+ for (const auto *ExistingPNA : D->specific_attrs<PreferredNameAttr>())
+ if (S.Context.hasSameType(ExistingPNA->getTypedefType(),
+ PNA->getTypedefType()))
+ return false;
+ return true;
+ }
+
+ return true;
+}
+
void Sema::InstantiateAttrsForDecl(
const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl,
Decl *New, LateInstantiatedAttrVec *LateAttrs,
LocalInstantiationScope *OuterMostScope) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(New)) {
+ // FIXME: This function is called multiple times for the same template
+ // specialization. We should only instantiate attributes that were added
+ // since the previous instantiation.
for (const auto *TmplAttr : Tmpl->attrs()) {
+ if (!isRelevantAttr(*this, New, TmplAttr))
+ continue;
+
// FIXME: If any of the special case versions from InstantiateAttrs become
// applicable to template declaration, we'll need to add them here.
CXXThisScopeRAII ThisScope(
@@ -511,7 +590,7 @@ void Sema::InstantiateAttrsForDecl(
Attr *NewAttr = sema::instantiateTemplateAttributeForDecl(
TmplAttr, Context, *this, TemplateArgs);
- if (NewAttr)
+ if (NewAttr && isRelevantAttr(*this, New, NewAttr))
New->addAttr(NewAttr);
}
}
@@ -536,6 +615,9 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
LateInstantiatedAttrVec *LateAttrs,
LocalInstantiationScope *OuterMostScope) {
for (const auto *TmplAttr : Tmpl->attrs()) {
+ if (!isRelevantAttr(*this, New, TmplAttr))
+ continue;
+
// FIXME: This should be generalized to more than just the AlignedAttr.
const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr);
if (Aligned && Aligned->isAlignmentDependent()) {
@@ -558,6 +640,10 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
continue;
}
+ if (const auto *Annotate = dyn_cast<AnnotateAttr>(TmplAttr)) {
+ instantiateDependentAnnotationAttr(*this, TemplateArgs, Annotate, New);
+ continue;
+ }
if (const auto *EnableIf = dyn_cast<EnableIfAttr>(TmplAttr)) {
instantiateDependentEnableIfAttr(*this, TemplateArgs, EnableIf, Tmpl,
@@ -654,12 +740,32 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context,
*this, TemplateArgs);
- if (NewAttr)
+ if (NewAttr && isRelevantAttr(*this, New, TmplAttr))
New->addAttr(NewAttr);
}
}
}
+/// In the MS ABI, we need to instantiate default arguments of dllexported
+/// default constructors along with the constructor definition. This allows IR
+/// gen to emit a constructor closure which calls the default constructor with
+/// its default arguments.
+void Sema::InstantiateDefaultCtorDefaultArgs(CXXConstructorDecl *Ctor) {
+ assert(Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ Ctor->isDefaultConstructor());
+ unsigned NumParams = Ctor->getNumParams();
+ if (NumParams == 0)
+ return;
+ DLLExportAttr *Attr = Ctor->getAttr<DLLExportAttr>();
+ if (!Attr)
+ return;
+ for (unsigned I = 0; I != NumParams; ++I) {
+ (void)CheckCXXDefaultArgExpr(Attr->getLocation(), Ctor,
+ Ctor->getParamDecl(I));
+ DiscardCleanupsInEvaluationContext();
+ }
+}
+
/// 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
@@ -702,6 +808,11 @@ Decl *TemplateDeclInstantiator::VisitMSGuidDecl(MSGuidDecl *D) {
llvm_unreachable("GUID declaration cannot be instantiated");
}
+Decl *TemplateDeclInstantiator::VisitTemplateParamObjectDecl(
+ TemplateParamObjectDecl *D) {
+ llvm_unreachable("template parameter objects cannot be instantiated");
+}
+
Decl *
TemplateDeclInstantiator::VisitLabelDecl(LabelDecl *D) {
LabelDecl *Inst = LabelDecl::Create(SemaRef.Context, Owner, D->getLocation(),
@@ -1911,7 +2022,6 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
D->hasWrittenPrototype(), D->getConstexprKind(),
TrailingRequiresClause);
Function->setRangeEnd(D->getSourceRange().getEnd());
- Function->setUsesFPIntrin(D->usesFPIntrin());
}
if (D->isInlined())
@@ -1981,8 +2091,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
}
- if (isFriend)
+ if (isFriend) {
Function->setObjectOfFriendDecl();
+ if (FunctionTemplateDecl *FT = Function->getDescribedFunctionTemplate())
+ FT->setObjectOfFriendDecl();
+ }
if (InitFunctionInstantiation(Function, D))
Function->setInvalidDecl();
@@ -2053,68 +2166,45 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
// typedef (C++ [dcl.typedef]p4).
if (Previous.isSingleTagDecl())
Previous.clear();
+
+ // Filter out previous declarations that don't match the scope. The only
+ // effect this has is to remove declarations found in inline namespaces
+ // for friend declarations with unqualified names.
+ SemaRef.FilterLookupForScope(Previous, DC, /*Scope*/ nullptr,
+ /*ConsiderLinkage*/ true,
+ QualifierLoc.hasQualifier());
}
SemaRef.CheckFunctionDeclaration(/*Scope*/ nullptr, Function, Previous,
IsExplicitSpecialization);
- NamedDecl *PrincipalDecl = (TemplateParams
- ? cast<NamedDecl>(FunctionTemplate)
- : Function);
-
- // If the original function was part of a friend declaration,
- // inherit its namespace state and add it to the owner.
- if (isFriend) {
- Function->setObjectOfFriendDecl();
- if (FunctionTemplateDecl *FT = Function->getDescribedFunctionTemplate())
- FT->setObjectOfFriendDecl();
- DC->makeDeclVisibleInContext(PrincipalDecl);
-
- bool QueuedInstantiation = false;
-
- // C++11 [temp.friend]p4 (DR329):
- // When a function is defined in a friend function declaration in a class
- // template, the function is instantiated when the function is odr-used.
- // The same restrictions on multiple declarations and definitions that
- // apply to non-template function declarations and definitions also apply
- // to these implicit definitions.
- if (D->isThisDeclarationADefinition()) {
- SemaRef.CheckForFunctionRedefinition(Function);
- if (!Function->isInvalidDecl()) {
- for (auto R : Function->redecls()) {
- if (R == Function)
- continue;
-
- // If some prior declaration of this function has been used, we need
- // to instantiate its definition.
- if (!QueuedInstantiation && R->isUsed(false)) {
- if (MemberSpecializationInfo *MSInfo =
- Function->getMemberSpecializationInfo()) {
- if (MSInfo->getPointOfInstantiation().isInvalid()) {
- SourceLocation Loc = R->getLocation(); // FIXME
- MSInfo->setPointOfInstantiation(Loc);
- SemaRef.PendingLocalImplicitInstantiations.push_back(
- std::make_pair(Function, Loc));
- QueuedInstantiation = true;
- }
- }
- }
- }
+ // Check the template parameter list against the previous declaration. The
+ // goal here is to pick up default arguments added since the friend was
+ // declared; we know the template parameter lists match, since otherwise
+ // we would not have picked this template as the previous declaration.
+ if (isFriend && TemplateParams && FunctionTemplate->getPreviousDecl()) {
+ SemaRef.CheckTemplateParameterList(
+ TemplateParams,
+ FunctionTemplate->getPreviousDecl()->getTemplateParameters(),
+ Function->isThisDeclarationADefinition()
+ ? Sema::TPC_FriendFunctionTemplateDefinition
+ : Sema::TPC_FriendFunctionTemplate);
+ }
+
+ // If we're introducing a friend definition after the first use, trigger
+ // instantiation.
+ // FIXME: If this is a friend function template definition, we should check
+ // to see if any specializations have been used.
+ if (isFriend && D->isThisDeclarationADefinition() && Function->isUsed(false)) {
+ if (MemberSpecializationInfo *MSInfo =
+ Function->getMemberSpecializationInfo()) {
+ if (MSInfo->getPointOfInstantiation().isInvalid()) {
+ SourceLocation Loc = D->getLocation(); // FIXME
+ MSInfo->setPointOfInstantiation(Loc);
+ SemaRef.PendingLocalImplicitInstantiations.push_back(
+ std::make_pair(Function, Loc));
}
}
-
- // Check the template parameter list against the previous declaration. The
- // goal here is to pick up default arguments added since the friend was
- // declared; we know the template parameter lists match, since otherwise
- // we would not have picked this template as the previous declaration.
- if (TemplateParams && FunctionTemplate->getPreviousDecl()) {
- SemaRef.CheckTemplateParameterList(
- TemplateParams,
- FunctionTemplate->getPreviousDecl()->getTemplateParameters(),
- Function->isThisDeclarationADefinition()
- ? Sema::TPC_FriendFunctionTemplateDefinition
- : Sema::TPC_FriendFunctionTemplate);
- }
}
if (D->isExplicitlyDefaulted()) {
@@ -2124,7 +2214,13 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
if (D->isDeleted())
SemaRef.SetDeclDeleted(Function, D->getLocation());
- if (Function->isLocalExternDecl() && !Function->getPreviousDecl())
+ NamedDecl *PrincipalDecl =
+ (TemplateParams ? cast<NamedDecl>(FunctionTemplate) : Function);
+
+ // If this declaration lives in a different context from its lexical context,
+ // add it to the corresponding lookup table.
+ if (isFriend ||
+ (Function->isLocalExternDecl() && !Function->getPreviousDecl()))
DC->makeDeclVisibleInContext(PrincipalDecl);
if (Function->isOverloadedOperator() && !DC->isRecord() &&
@@ -2879,7 +2975,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
if (!TName.isNull())
Param->setDefaultArgument(
SemaRef.Context,
- TemplateArgumentLoc(TemplateArgument(TName),
+ TemplateArgumentLoc(SemaRef.Context, TemplateArgument(TName),
D->getDefaultArgument().getTemplateQualifierLoc(),
D->getDefaultArgument().getTemplateNameLoc()));
}
@@ -3326,67 +3422,58 @@ TemplateDeclInstantiator::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) {
SemaRef.CurrentInstantiationScope->findInstantiationOf(PrevDeclInScope)
->get<Decl *>());
}
- OMPDeclareMapperDecl *NewDMD = SemaRef.ActOnOpenMPDeclareMapperDirectiveStart(
- /*S=*/nullptr, Owner, D->getDeclName(), SubstMapperTy, D->getLocation(),
- VN, D->getAccess(), PrevDeclInScope);
- SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewDMD);
- SmallVector<OMPClause *, 6> Clauses;
bool IsCorrect = true;
- if (!RequiresInstantiation) {
- // Copy the mapper variable.
- NewDMD->setMapperVarRef(D->getMapperVarRef());
- // Copy map clauses from the original mapper.
- for (OMPClause *C : D->clauselists())
- Clauses.push_back(C);
- } else {
- // Instantiate the mapper variable.
- DeclarationNameInfo DirName;
- SemaRef.StartOpenMPDSABlock(llvm::omp::OMPD_declare_mapper, DirName,
- /*S=*/nullptr,
- (*D->clauselist_begin())->getBeginLoc());
- SemaRef.ActOnOpenMPDeclareMapperDirectiveVarDecl(
- NewDMD, /*S=*/nullptr, SubstMapperTy, D->getLocation(), VN);
- SemaRef.CurrentInstantiationScope->InstantiatedLocal(
- cast<DeclRefExpr>(D->getMapperVarRef())->getDecl(),
- cast<DeclRefExpr>(NewDMD->getMapperVarRef())->getDecl());
- auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner);
- Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, Qualifiers(),
- ThisContext);
- // Instantiate map clauses.
- for (OMPClause *C : D->clauselists()) {
- auto *OldC = cast<OMPMapClause>(C);
- SmallVector<Expr *, 4> NewVars;
- for (Expr *OE : OldC->varlists()) {
- Expr *NE = SemaRef.SubstExpr(OE, TemplateArgs).get();
- if (!NE) {
- IsCorrect = false;
- break;
- }
- NewVars.push_back(NE);
- }
- if (!IsCorrect)
+ SmallVector<OMPClause *, 6> Clauses;
+ // Instantiate the mapper variable.
+ DeclarationNameInfo DirName;
+ SemaRef.StartOpenMPDSABlock(llvm::omp::OMPD_declare_mapper, DirName,
+ /*S=*/nullptr,
+ (*D->clauselist_begin())->getBeginLoc());
+ ExprResult MapperVarRef = SemaRef.ActOnOpenMPDeclareMapperDirectiveVarDecl(
+ /*S=*/nullptr, SubstMapperTy, D->getLocation(), VN);
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(
+ cast<DeclRefExpr>(D->getMapperVarRef())->getDecl(),
+ cast<DeclRefExpr>(MapperVarRef.get())->getDecl());
+ auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner);
+ Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, Qualifiers(),
+ ThisContext);
+ // Instantiate map clauses.
+ for (OMPClause *C : D->clauselists()) {
+ auto *OldC = cast<OMPMapClause>(C);
+ SmallVector<Expr *, 4> NewVars;
+ for (Expr *OE : OldC->varlists()) {
+ Expr *NE = SemaRef.SubstExpr(OE, TemplateArgs).get();
+ if (!NE) {
+ IsCorrect = false;
break;
- NestedNameSpecifierLoc NewQualifierLoc =
- SemaRef.SubstNestedNameSpecifierLoc(OldC->getMapperQualifierLoc(),
- TemplateArgs);
- CXXScopeSpec SS;
- SS.Adopt(NewQualifierLoc);
- DeclarationNameInfo NewNameInfo = SemaRef.SubstDeclarationNameInfo(
- OldC->getMapperIdInfo(), TemplateArgs);
- OMPVarListLocTy Locs(OldC->getBeginLoc(), OldC->getLParenLoc(),
- OldC->getEndLoc());
- OMPClause *NewC = SemaRef.ActOnOpenMPMapClause(
- OldC->getMapTypeModifiers(), OldC->getMapTypeModifiersLoc(), SS,
- NewNameInfo, OldC->getMapType(), OldC->isImplicitMapType(),
- OldC->getMapLoc(), OldC->getColonLoc(), NewVars, Locs);
- Clauses.push_back(NewC);
+ }
+ NewVars.push_back(NE);
}
- SemaRef.EndOpenMPDSABlock(nullptr);
- }
- (void)SemaRef.ActOnOpenMPDeclareMapperDirectiveEnd(NewDMD, /*S=*/nullptr,
- Clauses);
+ if (!IsCorrect)
+ break;
+ NestedNameSpecifierLoc NewQualifierLoc =
+ SemaRef.SubstNestedNameSpecifierLoc(OldC->getMapperQualifierLoc(),
+ TemplateArgs);
+ CXXScopeSpec SS;
+ SS.Adopt(NewQualifierLoc);
+ DeclarationNameInfo NewNameInfo =
+ SemaRef.SubstDeclarationNameInfo(OldC->getMapperIdInfo(), TemplateArgs);
+ OMPVarListLocTy Locs(OldC->getBeginLoc(), OldC->getLParenLoc(),
+ OldC->getEndLoc());
+ OMPClause *NewC = SemaRef.ActOnOpenMPMapClause(
+ OldC->getMapTypeModifiers(), OldC->getMapTypeModifiersLoc(), SS,
+ NewNameInfo, OldC->getMapType(), OldC->isImplicitMapType(),
+ OldC->getMapLoc(), OldC->getColonLoc(), NewVars, Locs);
+ Clauses.push_back(NewC);
+ }
+ SemaRef.EndOpenMPDSABlock(nullptr);
if (!IsCorrect)
return nullptr;
+ Sema::DeclGroupPtrTy DG = SemaRef.ActOnOpenMPDeclareMapperDirective(
+ /*S=*/nullptr, Owner, D->getDeclName(), SubstMapperTy, D->getLocation(),
+ VN, D->getAccess(), MapperVarRef.get(), Clauses, PrevDeclInScope);
+ Decl *NewDMD = DG.get().getSingleDecl();
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewDMD);
return NewDMD;
}
@@ -3595,11 +3682,11 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
return nullptr;
return VisitVarTemplateSpecializationDecl(
- InstVarTemplate, D, InsertPos, VarTemplateArgsInfo, Converted, PrevDecl);
+ InstVarTemplate, D, VarTemplateArgsInfo, Converted, PrevDecl);
}
Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
- VarTemplateDecl *VarTemplate, VarDecl *D, void *InsertPos,
+ VarTemplateDecl *VarTemplate, VarDecl *D,
const TemplateArgumentListInfo &TemplateArgsInfo,
ArrayRef<TemplateArgument> Converted,
VarTemplateSpecializationDecl *PrevDecl) {
@@ -3622,8 +3709,11 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(),
VarTemplate, DI->getType(), DI, D->getStorageClass(), Converted);
Var->setTemplateArgsInfo(TemplateArgsInfo);
- if (InsertPos)
+ if (!PrevDecl) {
+ void *InsertPos = nullptr;
+ VarTemplate->findSpecialization(Converted, InsertPos);
VarTemplate->AddSpecialization(Var, InsertPos);
+ }
if (SemaRef.getLangOpts().OpenCL)
SemaRef.deduceOpenCLAddressSpace(Var);
@@ -4099,6 +4189,9 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc.getNumParams();
OldIdx != NumOldParams; ++OldIdx) {
ParmVarDecl *OldParam = OldProtoLoc.getParam(OldIdx);
+ if (!OldParam)
+ return nullptr;
+
LocalInstantiationScope *Scope = SemaRef.CurrentInstantiationScope;
Optional<unsigned> NumArgumentsInExpansion;
@@ -4431,6 +4524,8 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
// into a template instantiation for this specific function template
// specialization, which is not a SFINAE context, so that we diagnose any
// further errors in the declaration itself.
+ //
+ // FIXME: This is a hack.
typedef Sema::CodeSynthesisContext ActiveInstType;
ActiveInstType &ActiveInst = SemaRef.CodeSynthesisContexts.back();
if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution ||
@@ -4440,6 +4535,8 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
assert(FunTmpl->getTemplatedDecl() == Tmpl &&
"Deduction from the wrong function template?");
(void) FunTmpl;
+ SemaRef.InstantiatingSpecializations.erase(
+ {ActiveInst.Entity->getCanonicalDecl(), ActiveInst.Kind});
atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst);
ActiveInst.Kind = ActiveInstType::TemplateInstantiation;
ActiveInst.Entity = New;
@@ -4569,27 +4666,6 @@ Sema::InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD,
return cast_or_null<FunctionDecl>(SubstDecl(FD, FD->getParent(), MArgs));
}
-/// In the MS ABI, we need to instantiate default arguments of dllexported
-/// default constructors along with the constructor definition. This allows IR
-/// gen to emit a constructor closure which calls the default constructor with
-/// its default arguments.
-static void InstantiateDefaultCtorDefaultArgs(Sema &S,
- CXXConstructorDecl *Ctor) {
- assert(S.Context.getTargetInfo().getCXXABI().isMicrosoft() &&
- Ctor->isDefaultConstructor());
- unsigned NumParams = Ctor->getNumParams();
- if (NumParams == 0)
- return;
- DLLExportAttr *Attr = Ctor->getAttr<DLLExportAttr>();
- if (!Attr)
- return;
- for (unsigned I = 0; I != NumParams; ++I) {
- (void)S.CheckCXXDefaultArgExpr(Attr->getLocation(), Ctor,
- Ctor->getParamDecl(I));
- S.DiscardCleanupsInEvaluationContext();
- }
-}
-
/// Instantiate the definition of the given function from its
/// template.
///
@@ -4612,8 +4688,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
bool Recursive,
bool DefinitionRequired,
bool AtEndOfTU) {
- if (Function->isInvalidDecl() || Function->isDefined() ||
- isa<CXXDeductionGuideDecl>(Function))
+ if (Function->isInvalidDecl() || isa<CXXDeductionGuideDecl>(Function))
return;
// Never instantiate an explicit specialization except if it is a class scope
@@ -4623,6 +4698,20 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
if (TSK == TSK_ExplicitSpecialization)
return;
+ // Don't instantiate a definition if we already have one.
+ const FunctionDecl *ExistingDefn = nullptr;
+ if (Function->isDefined(ExistingDefn,
+ /*CheckForPendingFriendDefinition=*/true)) {
+ if (ExistingDefn->isThisDeclarationADefinition())
+ return;
+
+ // If we're asked to instantiate a function whose body comes from an
+ // instantiated friend declaration, attach the instantiated body to the
+ // corresponding declaration of the function.
+ assert(ExistingDefn->isThisDeclarationInstantiatedFromAFriendDefinition());
+ Function = const_cast<FunctionDecl*>(ExistingDefn);
+ }
+
// Find the function body that we'll be substituting.
const FunctionDecl *PatternDecl = Function->getTemplateInstantiationPattern();
assert(PatternDecl && "instantiating a non-template");
@@ -4795,7 +4884,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
// default arguments.
if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
Ctor->isDefaultConstructor()) {
- InstantiateDefaultCtorDefaultArgs(*this, Ctor);
+ InstantiateDefaultCtorDefaultArgs(Ctor);
}
}
@@ -4832,7 +4921,7 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
const TemplateArgumentList &TemplateArgList,
const TemplateArgumentListInfo &TemplateArgsInfo,
SmallVectorImpl<TemplateArgument> &Converted,
- SourceLocation PointOfInstantiation, void *InsertPos,
+ SourceLocation PointOfInstantiation,
LateInstantiatedAttrVec *LateAttrs,
LocalInstantiationScope *StartingScope) {
if (FromVar->isInvalidDecl())
@@ -4871,7 +4960,7 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
return cast_or_null<VarTemplateSpecializationDecl>(
Instantiator.VisitVarTemplateSpecializationDecl(
- VarTemplate, FromVar, InsertPos, TemplateArgsInfo, Converted));
+ VarTemplate, FromVar, TemplateArgsInfo, Converted));
}
/// Instantiates a variable template specialization by completing it
@@ -5143,15 +5232,6 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
VarTemplateSpecializationDecl *VarSpec =
dyn_cast<VarTemplateSpecializationDecl>(Var);
if (VarSpec) {
- // If this is a variable template specialization, make sure that it is
- // non-dependent.
- bool InstantiationDependent = false;
- assert(!TemplateSpecializationType::anyDependentTemplateArguments(
- VarSpec->getTemplateArgsInfo(), InstantiationDependent) &&
- "Only instantiate variable template specializations that are "
- "not type-dependent");
- (void)InstantiationDependent;
-
// If this is a static data member template, there might be an
// uninstantiated initializer on the declaration. If so, instantiate
// it now.
@@ -5303,8 +5383,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
TemplateDeclInstantiator Instantiator(*this, Var->getDeclContext(),
TemplateArgs);
Var = cast_or_null<VarDecl>(Instantiator.VisitVarTemplateSpecializationDecl(
- VarSpec->getSpecializedTemplate(), Def, nullptr,
- VarSpec->getTemplateArgsInfo(), VarSpec->getTemplateArgs().asArray()));
+ VarSpec->getSpecializedTemplate(), Def, VarSpec->getTemplateArgsInfo(),
+ VarSpec->getTemplateArgs().asArray(), VarSpec));
if (Var) {
llvm::PointerUnion<VarTemplateDecl *,
VarTemplatePartialSpecializationDecl *> PatternPtr =
@@ -5314,12 +5394,6 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
cast<VarTemplateSpecializationDecl>(Var)->setInstantiationOf(
Partial, &VarSpec->getTemplateInstantiationArgs());
- // Merge the definition with the declaration.
- LookupResult R(*this, Var->getDeclName(), Var->getLocation(),
- LookupOrdinaryName, forRedeclarationInCurContext());
- R.addDecl(OldVar);
- MergeVarDecl(Var, R);
-
// Attach the initializer.
InstantiateVariableInitializer(Var, Def, TemplateArgs);
}
@@ -5972,16 +6046,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
return nullptr;
DeclContext::lookup_result Found = ParentDC->lookup(Name);
- if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(D)) {
- VarTemplateDecl *Templ = cast_or_null<VarTemplateDecl>(
- findInstantiationOf(Context, VTSD->getSpecializedTemplate(),
- Found.begin(), Found.end()));
- if (!Templ)
- return nullptr;
- Result = getVarTemplateSpecialization(
- Templ, &VTSD->getTemplateArgsInfo(), NewNameInfo, SourceLocation());
- } else
- Result = findInstantiationOf(Context, D, Found.begin(), Found.end());
+ Result = findInstantiationOf(Context, D, Found.begin(), Found.end());
} else {
// Since we don't have a name for the entity we're looking for,
// our only option is to walk through all of the declarations to
@@ -5999,7 +6064,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
if (!Result) {
if (isa<UsingShadowDecl>(D)) {
// UsingShadowDecls can instantiate to nothing because of using hiding.
- } else if (Diags.hasUncompilableErrorOccurred()) {
+ } else if (hasUncompilableErrorOccurred()) {
// We've already complained about some ill-formed code, so most likely
// this declaration failed to instantiate. There's no point in
// complaining further, since this is normal in invalid code.
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 7b77d1cb482a..1951aec3d17d 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -368,8 +368,8 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
Locations.push_back(Unexpanded[I].second);
}
- DiagnosticBuilder DB = Diag(Loc, diag::err_unexpanded_parameter_pack)
- << (int)UPPC << (int)Names.size();
+ auto DB = Diag(Loc, diag::err_unexpanded_parameter_pack)
+ << (int)UPPC << (int)Names.size();
for (size_t I = 0, E = std::min(Names.size(), (size_t)2); I != E; ++I)
DB << Names[I];
@@ -408,6 +408,29 @@ bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
return DiagnoseUnexpandedParameterPacks(E->getBeginLoc(), UPPC, Unexpanded);
}
+bool Sema::DiagnoseUnexpandedParameterPackInRequiresExpr(RequiresExpr *RE) {
+ if (!RE->containsUnexpandedParameterPack())
+ return false;
+
+ SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(RE);
+ assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+
+ // We only care about unexpanded references to the RequiresExpr's own
+ // parameter packs.
+ auto Parms = RE->getLocalParameters();
+ llvm::SmallPtrSet<NamedDecl*, 8> ParmSet(Parms.begin(), Parms.end());
+ SmallVector<UnexpandedParameterPack, 2> UnexpandedParms;
+ for (auto Parm : Unexpanded)
+ if (ParmSet.contains(Parm.first.dyn_cast<NamedDecl*>()))
+ UnexpandedParms.push_back(Parm);
+ if (UnexpandedParms.empty())
+ return false;
+
+ return DiagnoseUnexpandedParameterPacks(RE->getBeginLoc(), UPPC_Requirement,
+ UnexpandedParms);
+}
+
bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
UnexpandedParameterPackContext UPPC) {
// C++0x [temp.variadic]p5:
@@ -614,7 +637,8 @@ QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange PatternRange,
return QualType();
}
- return Context.getPackExpansionType(Pattern, NumExpansions);
+ return Context.getPackExpansionType(Pattern, NumExpansions,
+ /*ExpectPackInType=*/false);
}
ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) {
@@ -1071,7 +1095,7 @@ Sema::getTemplateArgumentPackExpansionPattern(
case TemplateArgument::TemplateExpansion:
Ellipsis = OrigLoc.getTemplateEllipsisLoc();
NumExpansions = Argument.getNumTemplateExpansions();
- return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
+ return TemplateArgumentLoc(Context, Argument.getPackExpansionPattern(),
OrigLoc.getTemplateQualifierLoc(),
OrigLoc.getTemplateNameLoc());
@@ -1159,7 +1183,7 @@ static void CheckFoldOperand(Sema &S, Expr *E) {
}
}
-ExprResult Sema::ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS,
+ExprResult Sema::ActOnCXXFoldExpr(Scope *S, SourceLocation LParenLoc, Expr *LHS,
tok::TokenKind Operator,
SourceLocation EllipsisLoc, Expr *RHS,
SourceLocation RParenLoc) {
@@ -1201,18 +1225,37 @@ ExprResult Sema::ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS,
}
BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Operator);
- return BuildCXXFoldExpr(LParenLoc, LHS, Opc, EllipsisLoc, RHS, RParenLoc,
+
+ // Perform first-phase name lookup now.
+ UnresolvedLookupExpr *ULE = nullptr;
+ {
+ UnresolvedSet<16> Functions;
+ LookupBinOp(S, EllipsisLoc, Opc, Functions);
+ if (!Functions.empty()) {
+ DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(
+ BinaryOperator::getOverloadedOperator(Opc));
+ ExprResult Callee = CreateUnresolvedLookupExpr(
+ /*NamingClass*/ nullptr, NestedNameSpecifierLoc(),
+ DeclarationNameInfo(OpName, EllipsisLoc), Functions);
+ if (Callee.isInvalid())
+ return ExprError();
+ ULE = cast<UnresolvedLookupExpr>(Callee.get());
+ }
+ }
+
+ return BuildCXXFoldExpr(ULE, LParenLoc, LHS, Opc, EllipsisLoc, RHS, RParenLoc,
None);
}
-ExprResult Sema::BuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS,
+ExprResult Sema::BuildCXXFoldExpr(UnresolvedLookupExpr *Callee,
+ SourceLocation LParenLoc, Expr *LHS,
BinaryOperatorKind Operator,
SourceLocation EllipsisLoc, Expr *RHS,
SourceLocation RParenLoc,
Optional<unsigned> NumExpansions) {
- return new (Context) CXXFoldExpr(Context.DependentTy, LParenLoc, LHS,
- Operator, EllipsisLoc, RHS, RParenLoc,
- NumExpansions);
+ return new (Context)
+ CXXFoldExpr(Context.DependentTy, Callee, LParenLoc, LHS, Operator,
+ EllipsisLoc, RHS, RParenLoc, NumExpansions);
}
ExprResult Sema::BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc,
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index b8f7f1a58159..4178024d1264 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -37,6 +37,7 @@
#include "llvm/ADT/StringSwitch.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/Support/ErrorHandling.h"
+#include <bitset>
using namespace clang;
@@ -49,7 +50,7 @@ enum TypeDiagSelector {
/// isOmittedBlockReturnType - Return true if this declarator is missing a
/// return type because this is a omitted return type on a block literal.
static bool isOmittedBlockReturnType(const Declarator &D) {
- if (D.getContext() != DeclaratorContext::BlockLiteralContext ||
+ if (D.getContext() != DeclaratorContext::BlockLiteral ||
D.getDeclSpec().hasTypeSpecifier())
return false;
@@ -146,6 +147,7 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr,
#define NULLABILITY_TYPE_ATTRS_CASELIST \
case ParsedAttr::AT_TypeNonNull: \
case ParsedAttr::AT_TypeNullable: \
+ case ParsedAttr::AT_TypeNullableResult: \
case ParsedAttr::AT_TypeNullUnspecified
namespace {
@@ -1299,27 +1301,27 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
Result = Context.VoidTy;
break;
case DeclSpec::TST_char:
- if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
+ if (DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified)
Result = Context.CharTy;
- else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed)
+ else if (DS.getTypeSpecSign() == TypeSpecifierSign::Signed)
Result = Context.SignedCharTy;
else {
- assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
+ assert(DS.getTypeSpecSign() == TypeSpecifierSign::Unsigned &&
"Unknown TSS value");
Result = Context.UnsignedCharTy;
}
break;
case DeclSpec::TST_wchar:
- if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
+ if (DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified)
Result = Context.WCharTy;
- else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) {
+ else if (DS.getTypeSpecSign() == TypeSpecifierSign::Signed) {
S.Diag(DS.getTypeSpecSignLoc(), diag::ext_wchar_t_sign_spec)
<< DS.getSpecifierName(DS.getTypeSpecType(),
Context.getPrintingPolicy());
Result = Context.getSignedWCharType();
} else {
- assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
- "Unknown TSS value");
+ assert(DS.getTypeSpecSign() == TypeSpecifierSign::Unsigned &&
+ "Unknown TSS value");
S.Diag(DS.getTypeSpecSignLoc(), diag::ext_wchar_t_sign_spec)
<< DS.getSpecifierName(DS.getTypeSpecType(),
Context.getPrintingPolicy());
@@ -1327,19 +1329,19 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
break;
case DeclSpec::TST_char8:
- assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
- "Unknown TSS value");
- Result = Context.Char8Ty;
+ assert(DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified &&
+ "Unknown TSS value");
+ Result = Context.Char8Ty;
break;
case DeclSpec::TST_char16:
- assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
- "Unknown TSS value");
- Result = Context.Char16Ty;
+ assert(DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified &&
+ "Unknown TSS value");
+ Result = Context.Char16Ty;
break;
case DeclSpec::TST_char32:
- assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
- "Unknown TSS value");
- Result = Context.Char32Ty;
+ assert(DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified &&
+ "Unknown TSS value");
+ Result = Context.Char32Ty;
break;
case DeclSpec::TST_unspecified:
// If this is a missing declspec in a block literal return context, then it
@@ -1347,12 +1349,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// The declspec is always missing in a lambda expr context; it is either
// specified with a trailing return type or inferred.
if (S.getLangOpts().CPlusPlus14 &&
- declarator.getContext() == DeclaratorContext::LambdaExprContext) {
+ declarator.getContext() == DeclaratorContext::LambdaExpr) {
// In C++1y, a lambda's implicit return type is 'auto'.
Result = Context.getAutoDeductType();
break;
- } else if (declarator.getContext() ==
- DeclaratorContext::LambdaExprContext ||
+ } else if (declarator.getContext() == DeclaratorContext::LambdaExpr ||
checkOmittedBlockReturnType(S, declarator,
Context.DependentTy)) {
Result = Context.DependentTy;
@@ -1401,12 +1402,18 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
LLVM_FALLTHROUGH;
case DeclSpec::TST_int: {
- if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) {
+ if (DS.getTypeSpecSign() != TypeSpecifierSign::Unsigned) {
switch (DS.getTypeSpecWidth()) {
- case DeclSpec::TSW_unspecified: Result = Context.IntTy; break;
- case DeclSpec::TSW_short: Result = Context.ShortTy; break;
- case DeclSpec::TSW_long: Result = Context.LongTy; break;
- case DeclSpec::TSW_longlong:
+ case TypeSpecifierWidth::Unspecified:
+ Result = Context.IntTy;
+ break;
+ case TypeSpecifierWidth::Short:
+ Result = Context.ShortTy;
+ break;
+ case TypeSpecifierWidth::Long:
+ Result = Context.LongTy;
+ break;
+ case TypeSpecifierWidth::LongLong:
Result = Context.LongLongTy;
// 'long long' is a C99 or C++11 feature.
@@ -1422,10 +1429,16 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
} else {
switch (DS.getTypeSpecWidth()) {
- case DeclSpec::TSW_unspecified: Result = Context.UnsignedIntTy; break;
- case DeclSpec::TSW_short: Result = Context.UnsignedShortTy; break;
- case DeclSpec::TSW_long: Result = Context.UnsignedLongTy; break;
- case DeclSpec::TSW_longlong:
+ case TypeSpecifierWidth::Unspecified:
+ Result = Context.UnsignedIntTy;
+ break;
+ case TypeSpecifierWidth::Short:
+ Result = Context.UnsignedShortTy;
+ break;
+ case TypeSpecifierWidth::Long:
+ Result = Context.UnsignedLongTy;
+ break;
+ case TypeSpecifierWidth::LongLong:
Result = Context.UnsignedLongLongTy;
// 'long long' is a C99 or C++11 feature.
@@ -1446,8 +1459,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
if (!S.Context.getTargetInfo().hasExtIntType())
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
<< "_ExtInt";
- Result = S.BuildExtIntType(DS.getTypeSpecSign() == TSS_unsigned,
- DS.getRepAsExpr(), DS.getBeginLoc());
+ Result =
+ S.BuildExtIntType(DS.getTypeSpecSign() == TypeSpecifierSign::Unsigned,
+ DS.getRepAsExpr(), DS.getBeginLoc());
if (Result.isNull()) {
Result = Context.IntTy;
declarator.setInvalidType(true);
@@ -1456,20 +1470,20 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
case DeclSpec::TST_accum: {
switch (DS.getTypeSpecWidth()) {
- case DeclSpec::TSW_short:
- Result = Context.ShortAccumTy;
- break;
- case DeclSpec::TSW_unspecified:
- Result = Context.AccumTy;
- break;
- case DeclSpec::TSW_long:
- Result = Context.LongAccumTy;
- break;
- case DeclSpec::TSW_longlong:
- llvm_unreachable("Unable to specify long long as _Accum width");
+ case TypeSpecifierWidth::Short:
+ Result = Context.ShortAccumTy;
+ break;
+ case TypeSpecifierWidth::Unspecified:
+ Result = Context.AccumTy;
+ break;
+ case TypeSpecifierWidth::Long:
+ Result = Context.LongAccumTy;
+ break;
+ case TypeSpecifierWidth::LongLong:
+ llvm_unreachable("Unable to specify long long as _Accum width");
}
- if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
+ if (DS.getTypeSpecSign() == TypeSpecifierSign::Unsigned)
Result = Context.getCorrespondingUnsignedType(Result);
if (DS.isTypeSpecSat())
@@ -1479,20 +1493,20 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
case DeclSpec::TST_fract: {
switch (DS.getTypeSpecWidth()) {
- case DeclSpec::TSW_short:
- Result = Context.ShortFractTy;
- break;
- case DeclSpec::TSW_unspecified:
- Result = Context.FractTy;
- break;
- case DeclSpec::TSW_long:
- Result = Context.LongFractTy;
- break;
- case DeclSpec::TSW_longlong:
- llvm_unreachable("Unable to specify long long as _Fract width");
+ case TypeSpecifierWidth::Short:
+ Result = Context.ShortFractTy;
+ break;
+ case TypeSpecifierWidth::Unspecified:
+ Result = Context.FractTy;
+ break;
+ case TypeSpecifierWidth::Long:
+ Result = Context.LongFractTy;
+ break;
+ case TypeSpecifierWidth::LongLong:
+ llvm_unreachable("Unable to specify long long as _Fract width");
}
- if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
+ if (DS.getTypeSpecSign() == TypeSpecifierSign::Unsigned)
Result = Context.getCorrespondingUnsignedType(Result);
if (DS.isTypeSpecSat())
@@ -1502,10 +1516,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
case DeclSpec::TST_int128:
if (!S.Context.getTargetInfo().hasInt128Type() &&
+ !S.getLangOpts().SYCLIsDevice &&
!(S.getLangOpts().OpenMP && S.getLangOpts().OpenMPIsDevice))
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
<< "__int128";
- if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
+ if (DS.getTypeSpecSign() == TypeSpecifierSign::Unsigned)
Result = Context.UnsignedInt128Ty;
else
Result = Context.Int128Ty;
@@ -1529,7 +1544,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
break;
case DeclSpec::TST_float: Result = Context.FloatTy; break;
case DeclSpec::TST_double:
- if (DS.getTypeSpecWidth() == DeclSpec::TSW_long)
+ if (DS.getTypeSpecWidth() == TypeSpecifierWidth::Long)
Result = Context.LongDoubleTy;
else
Result = Context.DoubleTy;
@@ -1542,7 +1557,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
<< "__float128";
Result = Context.Float128Ty;
break;
- case DeclSpec::TST_bool: Result = Context.BoolTy; break; // _Bool or bool
+ case DeclSpec::TST_bool:
+ Result = Context.BoolTy; // _Bool or bool
break;
case DeclSpec::TST_decimal32: // _Decimal32
case DeclSpec::TST_decimal64: // _Decimal64
@@ -1567,8 +1583,10 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// If the type is deprecated or unavailable, diagnose it.
S.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeNameLoc());
- assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
- DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!");
+ assert(DS.getTypeSpecWidth() == TypeSpecifierWidth::Unspecified &&
+ DS.getTypeSpecComplex() == 0 &&
+ DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified &&
+ "No qualifiers on tag names!");
// TypeQuals handled by caller.
Result = Context.getTypeDeclType(D);
@@ -1581,8 +1599,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
break;
}
case DeclSpec::TST_typename: {
- assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
- DS.getTypeSpecSign() == 0 &&
+ assert(DS.getTypeSpecWidth() == TypeSpecifierWidth::Unspecified &&
+ DS.getTypeSpecComplex() == 0 &&
+ DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified &&
"Can't handle qualifiers on typedef names yet!");
Result = S.GetTypeFromParser(DS.getRepAsType());
if (Result.isNull()) {
@@ -1739,7 +1758,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// Before we process any type attributes, synthesize a block literal
// function declarator if necessary.
- if (declarator.getContext() == DeclaratorContext::BlockLiteralContext)
+ if (declarator.getContext() == DeclaratorContext::BlockLiteral)
maybeSynthesizeBlockSignature(state, Result);
// Apply any type attributes from the decl spec. This may cause the
@@ -2070,7 +2089,8 @@ QualType Sema::BuildPointerType(QualType T,
return QualType();
}
- if (T->isFunctionType() && getLangOpts().OpenCL) {
+ if (T->isFunctionType() && getLangOpts().OpenCL &&
+ !getOpenCLOptions().isEnabled("__cl_clang_function_pointers")) {
Diag(Loc, diag::err_opencl_function_pointer);
return QualType();
}
@@ -2194,7 +2214,8 @@ QualType Sema::BuildExtIntType(bool IsUnsigned, Expr *BitWidth,
return Context.getDependentExtIntType(IsUnsigned, BitWidth);
llvm::APSInt Bits(32);
- ExprResult ICE = VerifyIntegerConstantExpression(BitWidth, &Bits);
+ ExprResult ICE =
+ VerifyIntegerConstantExpression(BitWidth, &Bits, /*FIXME*/ AllowFold);
if (ICE.isInvalid())
return QualType();
@@ -2219,26 +2240,62 @@ QualType Sema::BuildExtIntType(bool IsUnsigned, Expr *BitWidth,
return Context.getExtIntType(IsUnsigned, NumBits);
}
-/// Check whether the specified array size makes the array type a VLA. If so,
-/// return true, if not, return the size of the array in SizeVal.
-static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) {
+/// Check whether the specified array bound can be evaluated using the relevant
+/// language rules. If so, returns the possibly-converted expression and sets
+/// SizeVal to the size. If not, but the expression might be a VLA bound,
+/// returns ExprResult(). Otherwise, produces a diagnostic and returns
+/// ExprError().
+static ExprResult checkArraySize(Sema &S, Expr *&ArraySize,
+ llvm::APSInt &SizeVal, unsigned VLADiag,
+ bool VLAIsError) {
+ if (S.getLangOpts().CPlusPlus14 &&
+ (VLAIsError ||
+ !ArraySize->getType()->isIntegralOrUnscopedEnumerationType())) {
+ // C++14 [dcl.array]p1:
+ // The constant-expression shall be a converted constant expression of
+ // type std::size_t.
+ //
+ // Don't apply this rule if we might be forming a VLA: in that case, we
+ // allow non-constant expressions and constant-folding. We only need to use
+ // the converted constant expression rules (to properly convert the source)
+ // when the source expression is of class type.
+ return S.CheckConvertedConstantExpression(
+ ArraySize, S.Context.getSizeType(), SizeVal, Sema::CCEK_ArrayBound);
+ }
+
// If the size is an ICE, it certainly isn't a VLA. If we're in a GNU mode
// (like gnu99, but not c99) accept any evaluatable value as an extension.
class VLADiagnoser : public Sema::VerifyICEDiagnoser {
public:
- VLADiagnoser() : Sema::VerifyICEDiagnoser(true) {}
+ unsigned VLADiag;
+ bool VLAIsError;
+ bool IsVLA = false;
+
+ VLADiagnoser(unsigned VLADiag, bool VLAIsError)
+ : VLADiag(VLADiag), VLAIsError(VLAIsError) {}
- void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override {
+ Sema::SemaDiagnosticBuilder diagnoseNotICEType(Sema &S, SourceLocation Loc,
+ QualType T) override {
+ return S.Diag(Loc, diag::err_array_size_non_int) << T;
}
- void diagnoseFold(Sema &S, SourceLocation Loc, SourceRange SR) override {
- S.Diag(Loc, diag::ext_vla_folded_to_constant) << SR;
+ Sema::SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
+ SourceLocation Loc) override {
+ IsVLA = !VLAIsError;
+ return S.Diag(Loc, VLADiag);
}
- } Diagnoser;
- return S.VerifyIntegerConstantExpression(ArraySize, &SizeVal, Diagnoser,
- S.LangOpts.GNUMode ||
- S.LangOpts.OpenCL).isInvalid();
+ Sema::SemaDiagnosticBuilder diagnoseFold(Sema &S,
+ SourceLocation Loc) override {
+ return S.Diag(Loc, diag::ext_vla_folded_to_constant);
+ }
+ } Diagnoser(VLADiag, VLAIsError);
+
+ ExprResult R =
+ S.VerifyIntegerConstantExpression(ArraySize, &SizeVal, Diagnoser);
+ if (Diagnoser.IsVLA)
+ return ExprResult();
+ return R;
}
/// Build an array type.
@@ -2350,68 +2407,95 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
return QualType();
}
+ // VLAs always produce at least a -Wvla diagnostic, sometimes an error.
+ unsigned VLADiag;
+ bool VLAIsError;
+ if (getLangOpts().OpenCL) {
+ // OpenCL v1.2 s6.9.d: variable length arrays are not supported.
+ VLADiag = diag::err_opencl_vla;
+ VLAIsError = true;
+ } else if (getLangOpts().C99) {
+ VLADiag = diag::warn_vla_used;
+ VLAIsError = false;
+ } else if (isSFINAEContext()) {
+ VLADiag = diag::err_vla_in_sfinae;
+ VLAIsError = true;
+ } else {
+ VLADiag = diag::ext_vla;
+ VLAIsError = false;
+ }
+
llvm::APSInt ConstVal(Context.getTypeSize(Context.getSizeType()));
if (!ArraySize) {
- if (ASM == ArrayType::Star)
+ if (ASM == ArrayType::Star) {
+ Diag(Loc, VLADiag);
+ if (VLAIsError)
+ return QualType();
+
T = Context.getVariableArrayType(T, nullptr, ASM, Quals, Brackets);
- else
+ } else {
T = Context.getIncompleteArrayType(T, ASM, Quals);
+ }
} else if (ArraySize->isTypeDependent() || ArraySize->isValueDependent()) {
T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets);
- } else if ((!T->isDependentType() && !T->isIncompleteType() &&
- !T->isConstantSizeType()) ||
- isArraySizeVLA(*this, ArraySize, ConstVal)) {
- // Even in C++11, don't allow contextual conversions in the array bound
- // of a VLA.
- if (getLangOpts().CPlusPlus11 &&
- !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) {
- Diag(ArraySize->getBeginLoc(), diag::err_array_size_non_int)
- << ArraySize->getType() << ArraySize->getSourceRange();
+ } else {
+ ExprResult R =
+ checkArraySize(*this, ArraySize, ConstVal, VLADiag, VLAIsError);
+ if (R.isInvalid())
return QualType();
- }
- // C99: an array with an element type that has a non-constant-size is a VLA.
- // C99: an array with a non-ICE size is a VLA. We accept any expression
- // that we can fold to a non-zero positive value as an extension.
- T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
- } else {
- // C99 6.7.5.2p1: If the expression is a constant expression, it shall
- // have a value greater than zero.
- if (ConstVal.isSigned() && ConstVal.isNegative()) {
- if (Entity)
- Diag(ArraySize->getBeginLoc(), diag::err_decl_negative_array_size)
- << getPrintableNameForEntity(Entity) << ArraySize->getSourceRange();
- else
- Diag(ArraySize->getBeginLoc(), diag::err_typecheck_negative_array_size)
+ if (!R.isUsable()) {
+ // C99: an array with a non-ICE size is a VLA. We accept any expression
+ // that we can fold to a non-zero positive value as a non-VLA as an
+ // extension.
+ T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
+ } else if (!T->isDependentType() && !T->isIncompleteType() &&
+ !T->isConstantSizeType()) {
+ // C99: an array with an element type that has a non-constant-size is a
+ // VLA.
+ // FIXME: Add a note to explain why this isn't a VLA.
+ Diag(Loc, VLADiag);
+ if (VLAIsError)
+ return QualType();
+ T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
+ } else {
+ // C99 6.7.5.2p1: If the expression is a constant expression, it shall
+ // have a value greater than zero.
+ // In C++, this follows from narrowing conversions being disallowed.
+ if (ConstVal.isSigned() && ConstVal.isNegative()) {
+ if (Entity)
+ Diag(ArraySize->getBeginLoc(), diag::err_decl_negative_array_size)
+ << getPrintableNameForEntity(Entity)
+ << ArraySize->getSourceRange();
+ else
+ Diag(ArraySize->getBeginLoc(),
+ diag::err_typecheck_negative_array_size)
+ << ArraySize->getSourceRange();
+ return QualType();
+ }
+ if (ConstVal == 0) {
+ // GCC accepts zero sized static arrays. We allow them when
+ // we're not in a SFINAE context.
+ Diag(ArraySize->getBeginLoc(),
+ isSFINAEContext() ? diag::err_typecheck_zero_array_size
+ : diag::ext_typecheck_zero_array_size)
<< ArraySize->getSourceRange();
- return QualType();
- }
- if (ConstVal == 0) {
- // GCC accepts zero sized static arrays. We allow them when
- // we're not in a SFINAE context.
- Diag(ArraySize->getBeginLoc(), isSFINAEContext()
- ? diag::err_typecheck_zero_array_size
- : diag::ext_typecheck_zero_array_size)
- << ArraySize->getSourceRange();
- } else if (!T->isDependentType() && !T->isVariablyModifiedType() &&
- !T->isIncompleteType() && !T->isUndeducedType()) {
+ }
+
// Is the array too large?
- unsigned ActiveSizeBits
- = ConstantArrayType::getNumAddressingBits(Context, T, ConstVal);
+ unsigned ActiveSizeBits =
+ (!T->isDependentType() && !T->isVariablyModifiedType() &&
+ !T->isIncompleteType() && !T->isUndeducedType())
+ ? ConstantArrayType::getNumAddressingBits(Context, T, ConstVal)
+ : ConstVal.getActiveBits();
if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
Diag(ArraySize->getBeginLoc(), diag::err_array_too_large)
<< ConstVal.toString(10) << ArraySize->getSourceRange();
return QualType();
}
- }
- T = Context.getConstantArrayType(T, ConstVal, ArraySize, ASM, Quals);
- }
-
- // OpenCL v1.2 s6.9.d: variable length arrays are not supported.
- if (getLangOpts().OpenCL && T->isVariableArrayType()) {
- Diag(Loc, diag::err_opencl_vla);
- return QualType();
+ T = Context.getConstantArrayType(T, ConstVal, ArraySize, ASM, Quals);
+ }
}
if (T->isVariableArrayType() && !Context.getTargetInfo().isVLASupported()) {
@@ -2424,26 +2508,12 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
: CFT_InvalidTarget);
}
- // If this is not C99, extwarn about VLA's and C99 array size modifiers.
- if (!getLangOpts().C99) {
- if (T->isVariableArrayType()) {
- // Prohibit the use of VLAs during template argument deduction.
- if (isSFINAEContext()) {
- Diag(Loc, diag::err_vla_in_sfinae);
- return QualType();
- }
- // Just extwarn about VLAs.
- else
- Diag(Loc, diag::ext_vla);
- } else if (ASM != ArrayType::Normal || Quals != 0)
- Diag(Loc,
- getLangOpts().CPlusPlus? diag::err_c99_array_usage_cxx
- : diag::ext_c99_array_usage) << ASM;
- }
-
- if (T->isVariableArrayType()) {
- // Warn about VLAs for -Wvla.
- Diag(Loc, diag::warn_vla_used);
+ // If this is not C99, diagnose array size modifiers on non-VLAs.
+ if (!getLangOpts().C99 && !T->isVariableArrayType() &&
+ (ASM != ArrayType::Normal || Quals != 0)) {
+ Diag(Loc, getLangOpts().CPlusPlus ? diag::err_c99_array_usage_cxx
+ : diag::ext_c99_array_usage)
+ << ASM;
}
// OpenCL v2.0 s6.12.5 - Arrays of blocks are not supported.
@@ -2465,9 +2535,10 @@ QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr,
SourceLocation AttrLoc) {
// The base type must be integer (not Boolean or enumeration) or float, and
// can't already be a vector.
- if (!CurType->isDependentType() &&
- (!CurType->isBuiltinType() || CurType->isBooleanType() ||
- (!CurType->isIntegerType() && !CurType->isRealFloatingType()))) {
+ if ((!CurType->isDependentType() &&
+ (!CurType->isBuiltinType() || CurType->isBooleanType() ||
+ (!CurType->isIntegerType() && !CurType->isRealFloatingType()))) ||
+ CurType->isArrayType()) {
Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << CurType;
return QualType();
}
@@ -2476,8 +2547,8 @@ QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr,
return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc,
VectorType::GenericVector);
- llvm::APSInt VecSize(32);
- if (!SizeExpr->isIntegerConstantExpr(VecSize, Context)) {
+ Optional<llvm::APSInt> VecSize = SizeExpr->getIntegerConstantExpr(Context);
+ if (!VecSize) {
Diag(AttrLoc, diag::err_attribute_argument_type)
<< "vector_size" << AANT_ArgumentIntegerConstant
<< SizeExpr->getSourceRange();
@@ -2489,13 +2560,13 @@ QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr,
VectorType::GenericVector);
// vecSize is specified in bytes - convert to bits.
- if (!VecSize.isIntN(61)) {
+ if (!VecSize->isIntN(61)) {
// Bit size will overflow uint64.
Diag(AttrLoc, diag::err_attribute_size_too_large)
<< SizeExpr->getSourceRange() << "vector";
return QualType();
}
- uint64_t VectorSizeBits = VecSize.getZExtValue() * 8;
+ uint64_t VectorSizeBits = VecSize->getZExtValue() * 8;
unsigned TypeSize = static_cast<unsigned>(Context.getTypeSize(CurType));
if (VectorSizeBits == 0) {
@@ -2540,22 +2611,22 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
}
if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) {
- llvm::APSInt vecSize(32);
- if (!ArraySize->isIntegerConstantExpr(vecSize, Context)) {
+ Optional<llvm::APSInt> vecSize = ArraySize->getIntegerConstantExpr(Context);
+ if (!vecSize) {
Diag(AttrLoc, diag::err_attribute_argument_type)
<< "ext_vector_type" << AANT_ArgumentIntegerConstant
<< ArraySize->getSourceRange();
return QualType();
}
- if (!vecSize.isIntN(32)) {
+ if (!vecSize->isIntN(32)) {
Diag(AttrLoc, diag::err_attribute_size_too_large)
<< ArraySize->getSourceRange() << "vector";
return QualType();
}
// Unlike gcc's vector_size attribute, the size is specified as the
// number of elements, not the number of bytes.
- unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
+ unsigned vectorSize = static_cast<unsigned>(vecSize->getZExtValue());
if (vectorSize == 0) {
Diag(AttrLoc, diag::err_attribute_zero_size)
@@ -2586,18 +2657,15 @@ QualType Sema::BuildMatrixType(QualType ElementTy, Expr *NumRows, Expr *NumCols,
return Context.getDependentSizedMatrixType(ElementTy, NumRows, NumCols,
AttrLoc);
- // Both row and column values can only be 20 bit wide currently.
- llvm::APSInt ValueRows(32), ValueColumns(32);
-
- bool const RowsIsInteger = NumRows->isIntegerConstantExpr(ValueRows, Context);
- bool const ColumnsIsInteger =
- NumCols->isIntegerConstantExpr(ValueColumns, Context);
+ Optional<llvm::APSInt> ValueRows = NumRows->getIntegerConstantExpr(Context);
+ Optional<llvm::APSInt> ValueColumns =
+ NumCols->getIntegerConstantExpr(Context);
auto const RowRange = NumRows->getSourceRange();
auto const ColRange = NumCols->getSourceRange();
// Both are row and column expressions are invalid.
- if (!RowsIsInteger && !ColumnsIsInteger) {
+ if (!ValueRows && !ValueColumns) {
Diag(AttrLoc, diag::err_attribute_argument_type)
<< "matrix_type" << AANT_ArgumentIntegerConstant << RowRange
<< ColRange;
@@ -2605,22 +2673,22 @@ QualType Sema::BuildMatrixType(QualType ElementTy, Expr *NumRows, Expr *NumCols,
}
// Only the row expression is invalid.
- if (!RowsIsInteger) {
+ if (!ValueRows) {
Diag(AttrLoc, diag::err_attribute_argument_type)
<< "matrix_type" << AANT_ArgumentIntegerConstant << RowRange;
return QualType();
}
// Only the column expression is invalid.
- if (!ColumnsIsInteger) {
+ if (!ValueColumns) {
Diag(AttrLoc, diag::err_attribute_argument_type)
<< "matrix_type" << AANT_ArgumentIntegerConstant << ColRange;
return QualType();
}
// Check the matrix dimensions.
- unsigned MatrixRows = static_cast<unsigned>(ValueRows.getZExtValue());
- unsigned MatrixColumns = static_cast<unsigned>(ValueColumns.getZExtValue());
+ unsigned MatrixRows = static_cast<unsigned>(ValueRows->getZExtValue());
+ unsigned MatrixColumns = static_cast<unsigned>(ValueColumns->getZExtValue());
if (MatrixRows == 0 && MatrixColumns == 0) {
Diag(AttrLoc, diag::err_attribute_zero_size)
<< "matrix" << RowRange << ColRange;
@@ -3034,12 +3102,12 @@ void Sema::diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals,
static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy,
Declarator &D,
unsigned FunctionChunkIndex) {
- if (D.getTypeObject(FunctionChunkIndex).Fun.hasTrailingReturnType()) {
- // FIXME: TypeSourceInfo doesn't preserve location information for
- // qualifiers.
+ const DeclaratorChunk::FunctionTypeInfo &FTI =
+ D.getTypeObject(FunctionChunkIndex).Fun;
+ if (FTI.hasTrailingReturnType()) {
S.diagnoseIgnoredQualifiers(diag::warn_qual_return_type,
RetTy.getLocalCVRQualifiers(),
- D.getIdentifierLoc());
+ FTI.getTrailingReturnTypeLoc());
return;
}
@@ -3057,11 +3125,11 @@ static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy,
diag::warn_qual_return_type,
PTI.TypeQuals,
SourceLocation(),
- SourceLocation::getFromRawEncoding(PTI.ConstQualLoc),
- SourceLocation::getFromRawEncoding(PTI.VolatileQualLoc),
- SourceLocation::getFromRawEncoding(PTI.RestrictQualLoc),
- SourceLocation::getFromRawEncoding(PTI.AtomicQualLoc),
- SourceLocation::getFromRawEncoding(PTI.UnalignedQualLoc));
+ PTI.ConstQualLoc,
+ PTI.VolatileQualLoc,
+ PTI.RestrictQualLoc,
+ PTI.AtomicQualLoc,
+ PTI.UnalignedQualLoc);
return;
}
@@ -3101,24 +3169,10 @@ static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy,
D.getDeclSpec().getUnalignedSpecLoc());
}
-static void CopyTypeConstraintFromAutoType(Sema &SemaRef, const AutoType *Auto,
- AutoTypeLoc AutoLoc,
- TemplateTypeParmDecl *TP,
- SourceLocation EllipsisLoc) {
-
- TemplateArgumentListInfo TAL(AutoLoc.getLAngleLoc(), AutoLoc.getRAngleLoc());
- for (unsigned Idx = 0; Idx < AutoLoc.getNumArgs(); ++Idx)
- TAL.addArgument(AutoLoc.getArgLoc(Idx));
-
- SemaRef.AttachTypeConstraint(
- AutoLoc.getNestedNameSpecifierLoc(), AutoLoc.getConceptNameInfo(),
- AutoLoc.getNamedConcept(),
- AutoLoc.hasExplicitTemplateArgs() ? &TAL : nullptr, TP, EllipsisLoc);
-}
-
-static QualType InventTemplateParameter(
- TypeProcessingState &state, QualType T, TypeSourceInfo *TSI, AutoType *Auto,
- InventedTemplateParameterInfo &Info) {
+static std::pair<QualType, TypeSourceInfo *>
+InventTemplateParameter(TypeProcessingState &state, QualType T,
+ TypeSourceInfo *TrailingTSI, AutoType *Auto,
+ InventedTemplateParameterInfo &Info) {
Sema &S = state.getSema();
Declarator &D = state.getDeclarator();
@@ -3143,13 +3197,25 @@ static QualType InventTemplateParameter(
IsParameterPack, /*HasTypeConstraint=*/Auto->isConstrained());
InventedTemplateParam->setImplicit();
Info.TemplateParams.push_back(InventedTemplateParam);
- // Attach type constraints
+
+ // Attach type constraints to the new parameter.
if (Auto->isConstrained()) {
- if (TSI) {
- CopyTypeConstraintFromAutoType(
- S, Auto, TSI->getTypeLoc().getContainedAutoTypeLoc(),
- InventedTemplateParam, D.getEllipsisLoc());
+ if (TrailingTSI) {
+ // The 'auto' appears in a trailing return type we've already built;
+ // extract its type constraints to attach to the template parameter.
+ AutoTypeLoc AutoLoc = TrailingTSI->getTypeLoc().getContainedAutoTypeLoc();
+ TemplateArgumentListInfo TAL(AutoLoc.getLAngleLoc(), AutoLoc.getRAngleLoc());
+ for (unsigned Idx = 0; Idx < AutoLoc.getNumArgs(); ++Idx)
+ TAL.addArgument(AutoLoc.getArgLoc(Idx));
+
+ S.AttachTypeConstraint(AutoLoc.getNestedNameSpecifierLoc(),
+ AutoLoc.getConceptNameInfo(),
+ AutoLoc.getNamedConcept(),
+ AutoLoc.hasExplicitTemplateArgs() ? &TAL : nullptr,
+ InventedTemplateParam, D.getEllipsisLoc());
} else {
+ // The 'auto' appears in the decl-specifiers; we've not finished forming
+ // TypeSourceInfo for it yet.
TemplateIdAnnotation *TemplateId = D.getDeclSpec().getRepAsTemplateId();
TemplateArgumentListInfo TemplateArgsInfo;
if (TemplateId->LAngleLoc.isValid()) {
@@ -3167,15 +3233,16 @@ static QualType InventTemplateParameter(
}
}
- // If TSI is nullptr, this is a constrained declspec auto and the type
- // constraint will be attached later in TypeSpecLocFiller
-
// Replace the 'auto' in the function parameter with this invented
// template type parameter.
// FIXME: Retain some type sugar to indicate that this was written
// as 'auto'?
- return state.ReplaceAutoType(
- T, QualType(InventedTemplateParam->getTypeForDecl(), 0));
+ QualType Replacement(InventedTemplateParam->getTypeForDecl(), 0);
+ QualType NewT = state.ReplaceAutoType(T, Replacement);
+ TypeSourceInfo *NewTSI =
+ TrailingTSI ? S.ReplaceAutoTypeSourceInfo(TrailingTSI, Replacement)
+ : nullptr;
+ return {NewT, NewTSI};
}
static TypeSourceInfo *
@@ -3234,8 +3301,19 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
if (!D.getAttributes().empty())
distributeTypeAttrsFromDeclarator(state, T);
+ // Find the deduced type in this type. Look in the trailing return type if we
+ // have one, otherwise in the DeclSpec type.
+ // FIXME: The standard wording doesn't currently describe this.
+ DeducedType *Deduced = T->getContainedDeducedType();
+ bool DeducedIsTrailingReturnType = false;
+ if (Deduced && isa<AutoType>(Deduced) && D.hasTrailingReturnType()) {
+ QualType T = SemaRef.GetTypeFromParser(D.getTrailingReturnType());
+ Deduced = T.isNull() ? nullptr : T->getContainedDeducedType();
+ DeducedIsTrailingReturnType = true;
+ }
+
// C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context.
- if (DeducedType *Deduced = T->getContainedDeducedType()) {
+ if (Deduced) {
AutoType *Auto = dyn_cast<AutoType>(Deduced);
int Error = -1;
@@ -3246,21 +3324,21 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
bool IsDeducedReturnType = false;
switch (D.getContext()) {
- case DeclaratorContext::LambdaExprContext:
+ case DeclaratorContext::LambdaExpr:
// Declared return type of a lambda-declarator is implicit and is always
// 'auto'.
break;
- case DeclaratorContext::ObjCParameterContext:
- case DeclaratorContext::ObjCResultContext:
+ case DeclaratorContext::ObjCParameter:
+ case DeclaratorContext::ObjCResult:
Error = 0;
break;
- case DeclaratorContext::RequiresExprContext:
+ case DeclaratorContext::RequiresExpr:
Error = 22;
break;
- case DeclaratorContext::PrototypeContext:
- case DeclaratorContext::LambdaExprParameterContext: {
+ case DeclaratorContext::Prototype:
+ case DeclaratorContext::LambdaExprParameter: {
InventedTemplateParameterInfo *Info = nullptr;
- if (D.getContext() == DeclaratorContext::PrototypeContext) {
+ if (D.getContext() == DeclaratorContext::Prototype) {
// With concepts we allow 'auto' in function parameters.
if (!SemaRef.getLangOpts().CPlusPlus20 || !Auto ||
Auto->getKeyword() != AutoTypeKeyword::Auto) {
@@ -3269,10 +3347,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
} else if (!SemaRef.getCurScope()->isFunctionDeclarationScope()) {
Error = 21;
break;
- } else if (D.hasTrailingReturnType()) {
- // This might be OK, but we'll need to convert the trailing return
- // type later.
- break;
}
Info = &SemaRef.InventedParameterInfos.back();
@@ -3286,10 +3360,15 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
Info = SemaRef.getCurLambda();
assert(Info && "No LambdaScopeInfo on the stack!");
}
- T = InventTemplateParameter(state, T, nullptr, Auto, *Info);
+
+ // We'll deal with inventing template parameters for 'auto' in trailing
+ // return types when we pick up the trailing return type when processing
+ // the function chunk.
+ if (!DeducedIsTrailingReturnType)
+ T = InventTemplateParameter(state, T, nullptr, Auto, *Info).first;
break;
}
- case DeclaratorContext::MemberContext: {
+ case DeclaratorContext::Member: {
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
D.isFunctionDeclarator())
break;
@@ -3309,20 +3388,21 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
Error = 20; // Friend type
break;
}
- case DeclaratorContext::CXXCatchContext:
- case DeclaratorContext::ObjCCatchContext:
+ case DeclaratorContext::CXXCatch:
+ case DeclaratorContext::ObjCCatch:
Error = 7; // Exception declaration
break;
- case DeclaratorContext::TemplateParamContext:
- if (isa<DeducedTemplateSpecializationType>(Deduced))
- Error = 19; // Template parameter
+ case DeclaratorContext::TemplateParam:
+ if (isa<DeducedTemplateSpecializationType>(Deduced) &&
+ !SemaRef.getLangOpts().CPlusPlus20)
+ Error = 19; // Template parameter (until C++20)
else if (!SemaRef.getLangOpts().CPlusPlus17)
Error = 8; // Template parameter (until C++17)
break;
- case DeclaratorContext::BlockLiteralContext:
+ case DeclaratorContext::BlockLiteral:
Error = 9; // Block literal
break;
- case DeclaratorContext::TemplateArgContext:
+ case DeclaratorContext::TemplateArg:
// Within a template argument list, a deduced template specialization
// type will be reinterpreted as a template template argument.
if (isa<DeducedTemplateSpecializationType>(Deduced) &&
@@ -3330,47 +3410,47 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
D.getDeclSpec().getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier)
break;
LLVM_FALLTHROUGH;
- case DeclaratorContext::TemplateTypeArgContext:
+ case DeclaratorContext::TemplateTypeArg:
Error = 10; // Template type argument
break;
- case DeclaratorContext::AliasDeclContext:
- case DeclaratorContext::AliasTemplateContext:
+ case DeclaratorContext::AliasDecl:
+ case DeclaratorContext::AliasTemplate:
Error = 12; // Type alias
break;
- case DeclaratorContext::TrailingReturnContext:
- case DeclaratorContext::TrailingReturnVarContext:
+ case DeclaratorContext::TrailingReturn:
+ case DeclaratorContext::TrailingReturnVar:
if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
Error = 13; // Function return type
IsDeducedReturnType = true;
break;
- case DeclaratorContext::ConversionIdContext:
+ case DeclaratorContext::ConversionId:
if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
Error = 14; // conversion-type-id
IsDeducedReturnType = true;
break;
- case DeclaratorContext::FunctionalCastContext:
+ case DeclaratorContext::FunctionalCast:
if (isa<DeducedTemplateSpecializationType>(Deduced))
break;
LLVM_FALLTHROUGH;
- case DeclaratorContext::TypeNameContext:
+ case DeclaratorContext::TypeName:
Error = 15; // Generic
break;
- case DeclaratorContext::FileContext:
- case DeclaratorContext::BlockContext:
- case DeclaratorContext::ForContext:
- case DeclaratorContext::InitStmtContext:
- case DeclaratorContext::ConditionContext:
+ case DeclaratorContext::File:
+ case DeclaratorContext::Block:
+ case DeclaratorContext::ForInit:
+ case DeclaratorContext::SelectionInit:
+ case DeclaratorContext::Condition:
// FIXME: P0091R3 (erroneously) does not permit class template argument
// deduction in conditions, for-init-statements, and other declarations
// that are not simple-declarations.
break;
- case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::CXXNew:
// FIXME: P0091R3 does not permit class template argument deduction here,
// but we follow GCC and allow it anyway.
if (!IsCXXAutoType && !isa<DeducedTemplateSpecializationType>(Deduced))
Error = 17; // 'new' type
break;
- case DeclaratorContext::KNRTypeListContext:
+ case DeclaratorContext::KNRTypeList:
Error = 18; // K&R function parameter
break;
}
@@ -3384,20 +3464,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
(!SemaRef.getLangOpts().CPlusPlus11 || !IsCXXAutoType))
Error = 13;
- bool HaveTrailing = false;
-
- // C++11 [dcl.spec.auto]p2: 'auto' is always fine if the declarator
- // contains a trailing return type. That is only legal at the outermost
- // level. Check all declarator chunks (outermost first) anyway, to give
- // better diagnostics.
- // We don't support '__auto_type' with trailing return types.
- // FIXME: Should we only do this for 'auto' and not 'decltype(auto)'?
- if (SemaRef.getLangOpts().CPlusPlus11 && IsCXXAutoType &&
- D.hasTrailingReturnType()) {
- HaveTrailing = true;
- Error = -1;
- }
-
SourceRange AutoRange = D.getDeclSpec().getTypeSpecTypeLoc();
if (D.getName().getKind() == UnqualifiedIdKind::IK_ConversionFunctionId)
AutoRange = D.getName().getSourceRange();
@@ -3427,17 +3493,15 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
T = SemaRef.Context.IntTy;
D.setInvalidType(true);
- } else if (Auto && !HaveTrailing &&
- D.getContext() != DeclaratorContext::LambdaExprContext) {
+ } else if (Auto && D.getContext() != DeclaratorContext::LambdaExpr) {
// If there was a trailing return type, we already got
// warn_cxx98_compat_trailing_return_type in the parser.
SemaRef.Diag(AutoRange.getBegin(),
- D.getContext() ==
- DeclaratorContext::LambdaExprParameterContext
+ D.getContext() == DeclaratorContext::LambdaExprParameter
? diag::warn_cxx11_compat_generic_lambda
- : IsDeducedReturnType
- ? diag::warn_cxx11_compat_deduced_return_type
- : diag::warn_cxx98_compat_auto_type_specifier)
+ : IsDeducedReturnType
+ ? diag::warn_cxx11_compat_deduced_return_type
+ : diag::warn_cxx98_compat_auto_type_specifier)
<< AutoRange;
}
}
@@ -3448,50 +3512,50 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// or enumeration in a type-specifier-seq.
unsigned DiagID = 0;
switch (D.getContext()) {
- case DeclaratorContext::TrailingReturnContext:
- case DeclaratorContext::TrailingReturnVarContext:
+ case DeclaratorContext::TrailingReturn:
+ case DeclaratorContext::TrailingReturnVar:
// Class and enumeration definitions are syntactically not allowed in
// trailing return types.
llvm_unreachable("parser should not have allowed this");
break;
- case DeclaratorContext::FileContext:
- case DeclaratorContext::MemberContext:
- case DeclaratorContext::BlockContext:
- case DeclaratorContext::ForContext:
- case DeclaratorContext::InitStmtContext:
- case DeclaratorContext::BlockLiteralContext:
- case DeclaratorContext::LambdaExprContext:
+ case DeclaratorContext::File:
+ case DeclaratorContext::Member:
+ case DeclaratorContext::Block:
+ case DeclaratorContext::ForInit:
+ case DeclaratorContext::SelectionInit:
+ case DeclaratorContext::BlockLiteral:
+ case DeclaratorContext::LambdaExpr:
// C++11 [dcl.type]p3:
// A type-specifier-seq shall not define a class or enumeration unless
// it appears in the type-id of an alias-declaration (7.1.3) that is not
// the declaration of a template-declaration.
- case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasDecl:
break;
- case DeclaratorContext::AliasTemplateContext:
+ case DeclaratorContext::AliasTemplate:
DiagID = diag::err_type_defined_in_alias_template;
break;
- case DeclaratorContext::TypeNameContext:
- case DeclaratorContext::FunctionalCastContext:
- case DeclaratorContext::ConversionIdContext:
- case DeclaratorContext::TemplateParamContext:
- case DeclaratorContext::CXXNewContext:
- case DeclaratorContext::CXXCatchContext:
- case DeclaratorContext::ObjCCatchContext:
- case DeclaratorContext::TemplateArgContext:
- case DeclaratorContext::TemplateTypeArgContext:
+ case DeclaratorContext::TypeName:
+ case DeclaratorContext::FunctionalCast:
+ case DeclaratorContext::ConversionId:
+ case DeclaratorContext::TemplateParam:
+ case DeclaratorContext::CXXNew:
+ case DeclaratorContext::CXXCatch:
+ case DeclaratorContext::ObjCCatch:
+ case DeclaratorContext::TemplateArg:
+ case DeclaratorContext::TemplateTypeArg:
DiagID = diag::err_type_defined_in_type_specifier;
break;
- case DeclaratorContext::PrototypeContext:
- case DeclaratorContext::LambdaExprParameterContext:
- case DeclaratorContext::ObjCParameterContext:
- case DeclaratorContext::ObjCResultContext:
- case DeclaratorContext::KNRTypeListContext:
- case DeclaratorContext::RequiresExprContext:
+ case DeclaratorContext::Prototype:
+ case DeclaratorContext::LambdaExprParameter:
+ case DeclaratorContext::ObjCParameter:
+ case DeclaratorContext::ObjCResult:
+ case DeclaratorContext::KNRTypeList:
+ case DeclaratorContext::RequiresExpr:
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.
DiagID = diag::err_type_defined_in_param_type;
break;
- case DeclaratorContext::ConditionContext:
+ case DeclaratorContext::Condition:
// C++ 6.4p2:
// The type-specifier-seq shall not contain typedef and shall not declare
// a new class or enumeration.
@@ -3532,15 +3596,14 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
// Only warn if this declarator is declaring a function at block scope, and
// doesn't have a storage class (such as 'extern') specified.
if (!D.isFunctionDeclarator() ||
- D.getFunctionDefinitionKind() != FDK_Declaration ||
+ D.getFunctionDefinitionKind() != FunctionDefinitionKind::Declaration ||
!S.CurContext->isFunctionOrMethod() ||
- D.getDeclSpec().getStorageClassSpec()
- != DeclSpec::SCS_unspecified)
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_unspecified)
return;
// Inside a condition, a direct initializer is not permitted. We allow one to
// be parsed in order to give better diagnostics in condition parsing.
- if (D.getContext() == DeclaratorContext::ConditionContext)
+ if (D.getContext() == DeclaratorContext::Condition)
return;
SourceRange ParenRange(DeclType.Loc, DeclType.EndLoc);
@@ -3656,7 +3719,7 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) {
case DeclaratorChunk::Function:
// In a new-type-id, function chunks require parentheses.
- if (D.getContext() == DeclaratorContext::CXXNewContext)
+ if (D.getContext() == DeclaratorContext::CXXNew)
return;
// FIXME: "A(f())" deserves a vexing-parse warning, not just a
// redundant-parens warning, but we don't know whether the function
@@ -3773,7 +3836,7 @@ static CallingConv getCCForDeclaratorChunk(
// in a member pointer.
IsCXXInstanceMethod =
D.getTypeObject(I).Kind == DeclaratorChunk::MemberPointer;
- } else if (D.getContext() == DeclaratorContext::LambdaExprContext) {
+ } else if (D.getContext() == DeclaratorContext::LambdaExpr) {
// This can only be a call operator for a lambda, which is an instance
// method.
IsCXXInstanceMethod = true;
@@ -3832,6 +3895,11 @@ IdentifierInfo *Sema::getNullabilityKeyword(NullabilityKind nullability) {
Ident__Nullable = PP.getIdentifierInfo("_Nullable");
return Ident__Nullable;
+ case NullabilityKind::NullableResult:
+ if (!Ident__Nullable_result)
+ Ident__Nullable_result = PP.getIdentifierInfo("_Nullable_result");
+ return Ident__Nullable_result;
+
case NullabilityKind::Unspecified:
if (!Ident__Null_unspecified)
Ident__Null_unspecified = PP.getIdentifierInfo("_Null_unspecified");
@@ -3854,6 +3922,7 @@ static bool hasNullabilityAttr(const ParsedAttributesView &attrs) {
for (const ParsedAttr &AL : attrs) {
if (AL.getKind() == ParsedAttr::AT_TypeNonNull ||
AL.getKind() == ParsedAttr::AT_TypeNullable ||
+ AL.getKind() == ParsedAttr::AT_TypeNullableResult ||
AL.getKind() == ParsedAttr::AT_TypeNullUnspecified)
return true;
}
@@ -3998,32 +4067,9 @@ classifyPointerDeclarator(Sema &S, QualType type, Declarator &declarator,
if (auto recordType = type->getAs<RecordType>()) {
RecordDecl *recordDecl = recordType->getDecl();
- bool isCFError = false;
- if (S.CFError) {
- // If we already know about CFError, test it directly.
- isCFError = (S.CFError == recordDecl);
- } else {
- // Check whether this is CFError, which we identify based on its bridge
- // to NSError. CFErrorRef used to be declared with "objc_bridge" but is
- // now declared with "objc_bridge_mutable", so look for either one of
- // the two attributes.
- if (recordDecl->getTagKind() == TTK_Struct && numNormalPointers > 0) {
- IdentifierInfo *bridgedType = nullptr;
- if (auto bridgeAttr = recordDecl->getAttr<ObjCBridgeAttr>())
- bridgedType = bridgeAttr->getBridgedType();
- else if (auto bridgeAttr =
- recordDecl->getAttr<ObjCBridgeMutableAttr>())
- bridgedType = bridgeAttr->getBridgedType();
-
- if (bridgedType == S.getNSErrorIdent()) {
- S.CFError = recordDecl;
- isCFError = true;
- }
- }
- }
-
// If this is CFErrorRef*, report it as such.
- if (isCFError && numNormalPointers == 2 && numTypeSpecifierPointers < 2) {
+ if (numNormalPointers == 2 && numTypeSpecifierPointers < 2 &&
+ S.isCFError(recordDecl)) {
return PointerDeclaratorKind::CFErrorRefPointer;
}
break;
@@ -4047,6 +4093,31 @@ classifyPointerDeclarator(Sema &S, QualType type, Declarator &declarator,
}
}
+bool Sema::isCFError(RecordDecl *RD) {
+ // If we already know about CFError, test it directly.
+ if (CFError)
+ return CFError == RD;
+
+ // Check whether this is CFError, which we identify based on its bridge to
+ // NSError. CFErrorRef used to be declared with "objc_bridge" but is now
+ // declared with "objc_bridge_mutable", so look for either one of the two
+ // attributes.
+ if (RD->getTagKind() == TTK_Struct) {
+ IdentifierInfo *bridgedType = nullptr;
+ if (auto bridgeAttr = RD->getAttr<ObjCBridgeAttr>())
+ bridgedType = bridgeAttr->getBridgedType();
+ else if (auto bridgeAttr = RD->getAttr<ObjCBridgeMutableAttr>())
+ bridgedType = bridgeAttr->getBridgedType();
+
+ if (bridgedType == getNSErrorIdent()) {
+ CFError = RD;
+ return true;
+ }
+ }
+
+ return false;
+}
+
static FileID getNullabilityCompletenessCheckFileID(Sema &S,
SourceLocation loc) {
// If we're anywhere in a function, method, or closure context, don't perform
@@ -4086,7 +4157,8 @@ static FileID getNullabilityCompletenessCheckFileID(Sema &S,
/// Creates a fix-it to insert a C-style nullability keyword at \p pointerLoc,
/// taking into account whitespace before and after.
-static void fixItNullability(Sema &S, DiagnosticBuilder &Diag,
+template <typename DiagBuilderT>
+static void fixItNullability(Sema &S, DiagBuilderT &Diag,
SourceLocation PointerLoc,
NullabilityKind Nullability) {
assert(PointerLoc.isValid());
@@ -4269,6 +4341,9 @@ static Attr *createNullabilityAttr(ASTContext &Ctx, ParsedAttr &Attr,
case NullabilityKind::Nullable:
return createSimpleAttr<TypeNullableAttr>(Ctx, Attr);
+ case NullabilityKind::NullableResult:
+ return createSimpleAttr<TypeNullableResultAttr>(Ctx, Attr);
+
case NullabilityKind::Unspecified:
return createSimpleAttr<TypeNullUnspecifiedAttr>(Ctx, Attr);
}
@@ -4312,9 +4387,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Does this declaration declare a typedef-name?
bool IsTypedefName =
- D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef ||
- D.getContext() == DeclaratorContext::AliasDeclContext ||
- D.getContext() == DeclaratorContext::AliasTemplateContext;
+ D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef ||
+ D.getContext() == DeclaratorContext::AliasDecl ||
+ D.getContext() == DeclaratorContext::AliasTemplate;
// Does T refer to a function type with a cv-qualifier or a ref-qualifier?
bool IsQualifiedFunction = T->isFunctionProtoType() &&
@@ -4443,15 +4518,15 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
} else {
bool isFunctionOrMethod = false;
switch (auto context = state.getDeclarator().getContext()) {
- case DeclaratorContext::ObjCParameterContext:
- case DeclaratorContext::ObjCResultContext:
- case DeclaratorContext::PrototypeContext:
- case DeclaratorContext::TrailingReturnContext:
- case DeclaratorContext::TrailingReturnVarContext:
+ case DeclaratorContext::ObjCParameter:
+ case DeclaratorContext::ObjCResult:
+ case DeclaratorContext::Prototype:
+ case DeclaratorContext::TrailingReturn:
+ case DeclaratorContext::TrailingReturnVar:
isFunctionOrMethod = true;
LLVM_FALLTHROUGH;
- case DeclaratorContext::MemberContext:
+ case DeclaratorContext::Member:
if (state.getDeclarator().isObjCIvar() && !isFunctionOrMethod) {
complainAboutMissingNullability = CAMN_No;
break;
@@ -4465,8 +4540,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
LLVM_FALLTHROUGH;
- case DeclaratorContext::FileContext:
- case DeclaratorContext::KNRTypeListContext: {
+ case DeclaratorContext::File:
+ case DeclaratorContext::KNRTypeList: {
complainAboutMissingNullability = CAMN_Yes;
// Nullability inference depends on the type and declarator.
@@ -4482,9 +4557,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (inAssumeNonNullRegion) {
complainAboutInferringWithinChunk = wrappingKind;
inferNullability = NullabilityKind::NonNull;
- inferNullabilityCS =
- (context == DeclaratorContext::ObjCParameterContext ||
- context == DeclaratorContext::ObjCResultContext);
+ inferNullabilityCS = (context == DeclaratorContext::ObjCParameter ||
+ context == DeclaratorContext::ObjCResult);
}
break;
@@ -4520,28 +4594,28 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
break;
}
- case DeclaratorContext::ConversionIdContext:
+ case DeclaratorContext::ConversionId:
complainAboutMissingNullability = CAMN_Yes;
break;
- case DeclaratorContext::AliasDeclContext:
- case DeclaratorContext::AliasTemplateContext:
- case DeclaratorContext::BlockContext:
- case DeclaratorContext::BlockLiteralContext:
- case DeclaratorContext::ConditionContext:
- case DeclaratorContext::CXXCatchContext:
- case DeclaratorContext::CXXNewContext:
- case DeclaratorContext::ForContext:
- case DeclaratorContext::InitStmtContext:
- case DeclaratorContext::LambdaExprContext:
- case DeclaratorContext::LambdaExprParameterContext:
- case DeclaratorContext::ObjCCatchContext:
- case DeclaratorContext::TemplateParamContext:
- case DeclaratorContext::TemplateArgContext:
- case DeclaratorContext::TemplateTypeArgContext:
- case DeclaratorContext::TypeNameContext:
- case DeclaratorContext::FunctionalCastContext:
- case DeclaratorContext::RequiresExprContext:
+ case DeclaratorContext::AliasDecl:
+ case DeclaratorContext::AliasTemplate:
+ case DeclaratorContext::Block:
+ case DeclaratorContext::BlockLiteral:
+ case DeclaratorContext::Condition:
+ case DeclaratorContext::CXXCatch:
+ case DeclaratorContext::CXXNew:
+ case DeclaratorContext::ForInit:
+ case DeclaratorContext::SelectionInit:
+ case DeclaratorContext::LambdaExpr:
+ case DeclaratorContext::LambdaExprParameter:
+ case DeclaratorContext::ObjCCatch:
+ case DeclaratorContext::TemplateParam:
+ case DeclaratorContext::TemplateArg:
+ case DeclaratorContext::TemplateTypeArg:
+ case DeclaratorContext::TypeName:
+ case DeclaratorContext::FunctionalCast:
+ case DeclaratorContext::RequiresExpr:
// Don't infer in these contexts.
break;
}
@@ -4778,7 +4852,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// array type, ...
if (ASM == ArrayType::Static || ATI.TypeQuals) {
if (!(D.isPrototypeContext() ||
- D.getContext() == DeclaratorContext::KNRTypeListContext)) {
+ D.getContext() == DeclaratorContext::KNRTypeList)) {
S.Diag(DeclType.Loc, diag::err_array_static_outside_prototype) <<
(ASM == ArrayType::Static ? "'static'" : "type qualifier");
// Remove the 'static' and the type qualifiers.
@@ -4802,12 +4876,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
const AutoType *AT = T->getContainedAutoType();
// Allow arrays of auto if we are a generic lambda parameter.
// i.e. [](auto (&array)[5]) { return array[0]; }; OK
- if (AT &&
- D.getContext() != DeclaratorContext::LambdaExprParameterContext) {
+ if (AT && D.getContext() != DeclaratorContext::LambdaExprParameter) {
// We've already diagnosed this for decltype(auto).
if (!AT->isDecltypeAuto())
S.Diag(DeclType.Loc, diag::err_illegal_decl_array_of_auto)
- << getPrintableNameForEntity(Name) << T;
+ << getPrintableNameForEntity(Name) << T;
T = QualType();
break;
}
@@ -4866,7 +4939,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
<< D.getSourceRange();
D.setInvalidType(true);
}
- } else if (D.getContext() != DeclaratorContext::LambdaExprContext &&
+ } else if (D.getContext() != DeclaratorContext::LambdaExpr &&
(T.hasQualifiers() || !isa<AutoType>(T) ||
cast<AutoType>(T)->getKeyword() !=
AutoTypeKeyword::Auto ||
@@ -4881,12 +4954,20 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// An error occurred parsing the trailing return type.
T = Context.IntTy;
D.setInvalidType(true);
- } else if (S.getLangOpts().CPlusPlus20)
- // Handle cases like: `auto f() -> auto` or `auto f() -> C auto`.
- if (AutoType *Auto = T->getContainedAutoType())
- if (S.getCurScope()->isFunctionDeclarationScope())
- T = InventTemplateParameter(state, T, TInfo, Auto,
- S.InventedParameterInfos.back());
+ } else if (AutoType *Auto = T->getContainedAutoType()) {
+ // If the trailing return type contains an `auto`, we may need to
+ // invent a template parameter for it, for cases like
+ // `auto f() -> C auto` or `[](auto (*p) -> auto) {}`.
+ InventedTemplateParameterInfo *InventedParamInfo = nullptr;
+ if (D.getContext() == DeclaratorContext::Prototype)
+ InventedParamInfo = &S.InventedParameterInfos.back();
+ else if (D.getContext() == DeclaratorContext::LambdaExprParameter)
+ InventedParamInfo = S.getCurLambda();
+ if (InventedParamInfo) {
+ std::tie(T, TInfo) = InventTemplateParameter(
+ state, T, TInfo, Auto, *InventedParamInfo);
+ }
+ }
} else {
// This function type is not the type of the entity being declared,
// so checking the 'auto' is not the responsibility of this chunk.
@@ -4902,7 +4983,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Last processing chunk in block context means this function chunk
// represents the block.
if (chunkIndex == 0 &&
- D.getContext() == DeclaratorContext::BlockLiteralContext)
+ D.getContext() == DeclaratorContext::BlockLiteral)
diagID = diag::err_block_returning_array_function;
S.Diag(DeclType.Loc, diagID) << T->isFunctionType() << T;
T = Context.IntTy;
@@ -4938,6 +5019,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// (s6.9.e and s6.12.5 OpenCL v2.0) except for printf.
// We also allow here any toolchain reserved identifiers.
if (FTI.isVariadic &&
+ !S.getOpenCLOptions().isEnabled("__cl_clang_variadic_functions") &&
!(D.getIdentifier() &&
((D.getIdentifier()->getName() == "printf" &&
(LangOpts.OpenCLCPlusPlus || LangOpts.OpenCLVersion >= 120)) ||
@@ -4980,7 +5062,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
!(S.getLangOpts().CPlusPlus &&
(T->isDependentType() || T->isRecordType()))) {
if (T->isVoidType() && !S.getLangOpts().CPlusPlus &&
- D.getFunctionDefinitionKind() == FDK_Definition) {
+ D.getFunctionDefinitionKind() ==
+ FunctionDefinitionKind::Definition) {
// [6.9.1/3] qualified void return is invalid on a C
// function definition. Apparently ok on declarations and
// in C++ though (!)
@@ -5043,8 +5126,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (IsTypedefName && FTI.getExceptionSpecType() && !LangOpts.CPlusPlus17)
S.Diag(FTI.getExceptionSpecLocBeg(),
diag::err_exception_spec_in_typedef)
- << (D.getContext() == DeclaratorContext::AliasDeclContext ||
- D.getContext() == DeclaratorContext::AliasTemplateContext);
+ << (D.getContext() == DeclaratorContext::AliasDecl ||
+ D.getContext() == DeclaratorContext::AliasTemplate);
// If we see "T var();" or "T var(T());" at block scope, it is probably
// an attempt to initialize a variable, not a function declaration.
@@ -5111,7 +5194,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// is an incomplete type (C99 6.2.5p19) and function decls cannot
// have parameters of incomplete type.
if (FTI.NumParams != 1 || FTI.isVariadic) {
- S.Diag(DeclType.Loc, diag::err_void_only_param);
+ S.Diag(FTI.Params[i].IdentLoc, diag::err_void_only_param);
ParamTy = Context.IntTy;
Param->setType(ParamTy);
} else if (FTI.Params[i].Ident) {
@@ -5225,9 +5308,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
.getScopeRep()
->getKind() == NestedNameSpecifier::TypeSpec) ||
state.getDeclarator().getContext() ==
- DeclaratorContext::MemberContext ||
+ DeclaratorContext::Member ||
state.getDeclarator().getContext() ==
- DeclaratorContext::LambdaExprContext;
+ DeclaratorContext::LambdaExpr;
};
if (state.getSema().getLangOpts().OpenCLCPlusPlus && IsClassMember()) {
@@ -5351,7 +5434,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// The empty list in a function declarator that is not part of a definition
// of that function specifies that no information about the number or types
// of the parameters is supplied.
- if (!LangOpts.CPlusPlus && D.getFunctionDefinitionKind() == FDK_Declaration) {
+ if (!LangOpts.CPlusPlus &&
+ D.getFunctionDefinitionKind() == FunctionDefinitionKind::Declaration) {
bool IsBlock = false;
for (const DeclaratorChunk &DeclType : D.type_objects()) {
switch (DeclType.Kind) {
@@ -5394,8 +5478,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (D.getName().getKind() == UnqualifiedIdKind::IK_DeductionGuideName)
Kind = DeductionGuide;
else if (!D.getCXXScopeSpec().isSet()) {
- if ((D.getContext() == DeclaratorContext::MemberContext ||
- D.getContext() == DeclaratorContext::LambdaExprContext) &&
+ if ((D.getContext() == DeclaratorContext::Member ||
+ D.getContext() == DeclaratorContext::LambdaExpr) &&
!D.getDeclSpec().isFriendSpecified())
Kind = Member;
} else {
@@ -5423,9 +5507,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (IsQualifiedFunction &&
!(Kind == Member &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) &&
- !IsTypedefName &&
- D.getContext() != DeclaratorContext::TemplateArgContext &&
- D.getContext() != DeclaratorContext::TemplateTypeArgContext) {
+ !IsTypedefName && D.getContext() != DeclaratorContext::TemplateArg &&
+ D.getContext() != DeclaratorContext::TemplateTypeArg) {
SourceLocation Loc = D.getBeginLoc();
SourceRange RemovalRange;
unsigned I;
@@ -5480,15 +5563,15 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// C++0x [dcl.constexpr]p9:
// A constexpr specifier used in an object declaration declares the object
// as const.
- if (D.getDeclSpec().getConstexprSpecifier() == CSK_constexpr &&
+ if (D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr &&
T->isObjectType())
T.addConst();
// C++2a [dcl.fct]p4:
// A parameter with volatile-qualified type is deprecated
if (T.isVolatileQualified() && S.getLangOpts().CPlusPlus20 &&
- (D.getContext() == DeclaratorContext::PrototypeContext ||
- D.getContext() == DeclaratorContext::LambdaExprParameterContext))
+ (D.getContext() == DeclaratorContext::Prototype ||
+ D.getContext() == DeclaratorContext::LambdaExprParameter))
S.Diag(D.getIdentifierLoc(), diag::warn_deprecated_volatile_param) << T;
// If there was an ellipsis in the declarator, the declaration declares a
@@ -5499,9 +5582,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// only be used in a parameter-declaration. Such a parameter-declaration
// is a parameter pack (14.5.3). [...]
switch (D.getContext()) {
- case DeclaratorContext::PrototypeContext:
- case DeclaratorContext::LambdaExprParameterContext:
- case DeclaratorContext::RequiresExprContext:
+ case DeclaratorContext::Prototype:
+ case DeclaratorContext::LambdaExprParameter:
+ case DeclaratorContext::RequiresExpr:
// C++0x [dcl.fct]p13:
// [...] When it is part of a parameter-declaration-clause, the
// parameter pack is a function parameter pack (14.5.3). The type T
@@ -5518,10 +5601,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
<< T << D.getSourceRange();
D.setEllipsisLoc(SourceLocation());
} else {
- T = Context.getPackExpansionType(T, None);
+ T = Context.getPackExpansionType(T, None, /*ExpectPackInType=*/false);
}
break;
- case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::TemplateParam:
// C++0x [temp.param]p15:
// If a template-parameter is a [...] is a parameter-declaration that
// declares a parameter pack (8.3.5), then the template-parameter is a
@@ -5539,31 +5622,29 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
: diag::ext_variadic_templates);
break;
- case DeclaratorContext::FileContext:
- case DeclaratorContext::KNRTypeListContext:
- case DeclaratorContext::ObjCParameterContext: // FIXME: special diagnostic
- // here?
- case DeclaratorContext::ObjCResultContext: // FIXME: special diagnostic
- // here?
- case DeclaratorContext::TypeNameContext:
- case DeclaratorContext::FunctionalCastContext:
- case DeclaratorContext::CXXNewContext:
- case DeclaratorContext::AliasDeclContext:
- case DeclaratorContext::AliasTemplateContext:
- case DeclaratorContext::MemberContext:
- case DeclaratorContext::BlockContext:
- case DeclaratorContext::ForContext:
- case DeclaratorContext::InitStmtContext:
- case DeclaratorContext::ConditionContext:
- case DeclaratorContext::CXXCatchContext:
- case DeclaratorContext::ObjCCatchContext:
- case DeclaratorContext::BlockLiteralContext:
- case DeclaratorContext::LambdaExprContext:
- case DeclaratorContext::ConversionIdContext:
- case DeclaratorContext::TrailingReturnContext:
- case DeclaratorContext::TrailingReturnVarContext:
- case DeclaratorContext::TemplateArgContext:
- case DeclaratorContext::TemplateTypeArgContext:
+ case DeclaratorContext::File:
+ case DeclaratorContext::KNRTypeList:
+ case DeclaratorContext::ObjCParameter: // FIXME: special diagnostic here?
+ case DeclaratorContext::ObjCResult: // FIXME: special diagnostic here?
+ case DeclaratorContext::TypeName:
+ case DeclaratorContext::FunctionalCast:
+ case DeclaratorContext::CXXNew:
+ case DeclaratorContext::AliasDecl:
+ case DeclaratorContext::AliasTemplate:
+ case DeclaratorContext::Member:
+ case DeclaratorContext::Block:
+ case DeclaratorContext::ForInit:
+ case DeclaratorContext::SelectionInit:
+ case DeclaratorContext::Condition:
+ case DeclaratorContext::CXXCatch:
+ case DeclaratorContext::ObjCCatch:
+ case DeclaratorContext::BlockLiteral:
+ case DeclaratorContext::LambdaExpr:
+ case DeclaratorContext::ConversionId:
+ case DeclaratorContext::TrailingReturn:
+ case DeclaratorContext::TrailingReturnVar:
+ case DeclaratorContext::TemplateArg:
+ case DeclaratorContext::TemplateTypeArg:
// FIXME: We may want to allow parameter packs in block-literal contexts
// in the future.
S.Diag(D.getEllipsisLoc(),
@@ -5816,9 +5897,9 @@ namespace {
// Set info for the written builtin specifiers.
TL.getWrittenBuiltinSpecs() = DS.getWrittenBuiltinSpecs();
// Try to have a meaningful source location.
- if (TL.getWrittenSignSpec() != TSS_unspecified)
+ if (TL.getWrittenSignSpec() != TypeSpecifierSign::Unspecified)
TL.expandBuiltinRange(DS.getTypeSpecSignLoc());
- if (TL.getWrittenWidthSpec() != TSW_unspecified)
+ if (TL.getWrittenWidthSpec() != TypeSpecifierWidth::Unspecified)
TL.expandBuiltinRange(DS.getTypeSpecWidthRange());
}
}
@@ -6005,7 +6086,7 @@ namespace {
}
// Finally fill in MemberPointerLocInfo fields.
- TL.setStarLoc(SourceLocation::getFromRawEncoding(Chunk.Mem.StarLoc));
+ TL.setStarLoc(Chunk.Mem.StarLoc);
TL.setClassTInfo(ClsTInfo);
}
void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
@@ -6054,6 +6135,17 @@ namespace {
void VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) {
TL.setExpansionLoc(Chunk.Loc);
}
+ void VisitVectorTypeLoc(VectorTypeLoc TL) { TL.setNameLoc(Chunk.Loc); }
+ void VisitDependentVectorTypeLoc(DependentVectorTypeLoc TL) {
+ TL.setNameLoc(Chunk.Loc);
+ }
+ void VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
+ TL.setNameLoc(Chunk.Loc);
+ }
+ void
+ VisitDependentSizedExtVectorTypeLoc(DependentSizedExtVectorTypeLoc TL) {
+ TL.setNameLoc(Chunk.Loc);
+ }
void VisitTypeLoc(TypeLoc TL) {
llvm_unreachable("unsupported TypeLoc kind in declarator!");
@@ -6071,7 +6163,7 @@ static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) {
llvm_unreachable("cannot be _Atomic qualified");
case DeclaratorChunk::Pointer:
- Loc = SourceLocation::getFromRawEncoding(Chunk.Ptr.AtomicQualLoc);
+ Loc = Chunk.Ptr.AtomicQualLoc;
break;
case DeclaratorChunk::BlockPointer:
@@ -6224,9 +6316,9 @@ TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
// to apply them to the actual parameter declaration.
// Likewise, we don't want to do this for alias declarations, because
// we are actually going to build a declaration from this eventually.
- if (D.getContext() != DeclaratorContext::ObjCParameterContext &&
- D.getContext() != DeclaratorContext::AliasDeclContext &&
- D.getContext() != DeclaratorContext::AliasTemplateContext)
+ if (D.getContext() != DeclaratorContext::ObjCParameter &&
+ D.getContext() != DeclaratorContext::AliasDecl &&
+ D.getContext() != DeclaratorContext::AliasTemplate)
checkUnusedDeclAttributes(D);
if (getLangOpts().CPlusPlus) {
@@ -6254,13 +6346,15 @@ static bool BuildAddressSpaceIndex(Sema &S, LangAS &ASIdx,
const Expr *AddrSpace,
SourceLocation AttrLoc) {
if (!AddrSpace->isValueDependent()) {
- llvm::APSInt addrSpace(32);
- if (!AddrSpace->isIntegerConstantExpr(addrSpace, S.Context)) {
+ Optional<llvm::APSInt> OptAddrSpace =
+ AddrSpace->getIntegerConstantExpr(S.Context);
+ if (!OptAddrSpace) {
S.Diag(AttrLoc, diag::err_attribute_argument_type)
<< "'address_space'" << AANT_ArgumentIntegerConstant
<< AddrSpace->getSourceRange();
return false;
}
+ llvm::APSInt &addrSpace = *OptAddrSpace;
// Bounds checking.
if (addrSpace.isSigned()) {
@@ -6353,25 +6447,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
return;
}
- Expr *ASArgExpr;
- if (Attr.isArgIdent(0)) {
- // Special case where the argument is a template id.
- CXXScopeSpec SS;
- SourceLocation TemplateKWLoc;
- UnqualifiedId id;
- id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
-
- ExprResult AddrSpace = S.ActOnIdExpression(
- S.getCurScope(), SS, TemplateKWLoc, id, /*HasTrailingLParen=*/false,
- /*IsAddressOfOperand=*/false);
- if (AddrSpace.isInvalid())
- return;
-
- ASArgExpr = static_cast<Expr *>(AddrSpace.get());
- } else {
- ASArgExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
- }
-
+ Expr *ASArgExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
LangAS ASIdx;
if (!BuildAddressSpaceIndex(S, ASIdx, ASArgExpr, Attr.getLoc())) {
Attr.setInvalid();
@@ -6858,32 +6934,32 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
break;
}
- llvm::SmallSet<attr::Kind, 2> Attrs;
+ std::bitset<attr::LastAttr> Attrs;
attr::Kind NewAttrKind = A->getKind();
QualType Desugared = Type;
const AttributedType *AT = dyn_cast<AttributedType>(Type);
while (AT) {
- Attrs.insert(AT->getAttrKind());
+ Attrs[AT->getAttrKind()] = true;
Desugared = AT->getModifiedType();
AT = dyn_cast<AttributedType>(Desugared);
}
// You cannot specify duplicate type attributes, so if the attribute has
// already been applied, flag it.
- if (Attrs.count(NewAttrKind)) {
+ if (Attrs[NewAttrKind]) {
S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact) << PAttr;
return true;
}
- Attrs.insert(NewAttrKind);
+ Attrs[NewAttrKind] = true;
// You cannot have both __sptr and __uptr on the same type, nor can you
// have __ptr32 and __ptr64.
- if (Attrs.count(attr::Ptr32) && Attrs.count(attr::Ptr64)) {
+ if (Attrs[attr::Ptr32] && Attrs[attr::Ptr64]) {
S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
<< "'__ptr32'"
<< "'__ptr64'";
return true;
- } else if (Attrs.count(attr::SPtr) && Attrs.count(attr::UPtr)) {
+ } else if (Attrs[attr::SPtr] && Attrs[attr::UPtr]) {
S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
<< "'__sptr'"
<< "'__uptr'";
@@ -6909,12 +6985,12 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
LangAS ASIdx = LangAS::Default;
uint64_t PtrWidth = S.Context.getTargetInfo().getPointerWidth(0);
if (PtrWidth == 32) {
- if (Attrs.count(attr::Ptr64))
+ if (Attrs[attr::Ptr64])
ASIdx = LangAS::ptr64;
- else if (Attrs.count(attr::UPtr))
+ else if (Attrs[attr::UPtr])
ASIdx = LangAS::ptr32_uptr;
- } else if (PtrWidth == 64 && Attrs.count(attr::Ptr32)) {
- if (Attrs.count(attr::UPtr))
+ } else if (PtrWidth == 64 && Attrs[attr::Ptr32]) {
+ if (Attrs[attr::UPtr])
ASIdx = LangAS::ptr32_uptr;
else
ASIdx = LangAS::ptr32_sptr;
@@ -6937,6 +7013,9 @@ static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) {
case ParsedAttr::AT_TypeNullable:
return NullabilityKind::Nullable;
+ case ParsedAttr::AT_TypeNullableResult:
+ return NullabilityKind::NullableResult;
+
case ParsedAttr::AT_TypeNullUnspecified:
return NullabilityKind::Unspecified;
@@ -7574,25 +7653,7 @@ static void HandleVectorSizeAttr(QualType &CurType, const ParsedAttr &Attr,
return;
}
- Expr *SizeExpr;
- // Special case where the argument is a template id.
- if (Attr.isArgIdent(0)) {
- CXXScopeSpec SS;
- SourceLocation TemplateKWLoc;
- UnqualifiedId Id;
- Id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
-
- ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc,
- Id, /*HasTrailingLParen=*/false,
- /*IsAddressOfOperand=*/false);
-
- if (Size.isInvalid())
- return;
- SizeExpr = Size.get();
- } else {
- SizeExpr = Attr.getArgAsExpr(0);
- }
-
+ Expr *SizeExpr = Attr.getArgAsExpr(0);
QualType T = S.BuildVectorType(CurType, SizeExpr, Attr.getLoc());
if (!T.isNull())
CurType = T;
@@ -7611,28 +7672,8 @@ static void HandleExtVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
return;
}
- Expr *sizeExpr;
-
- // Special case where the argument is a template id.
- if (Attr.isArgIdent(0)) {
- CXXScopeSpec SS;
- SourceLocation TemplateKWLoc;
- UnqualifiedId id;
- id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
-
- ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc,
- id, /*HasTrailingLParen=*/false,
- /*IsAddressOfOperand=*/false);
- if (Size.isInvalid())
- return;
-
- sizeExpr = Size.get();
- } else {
- sizeExpr = Attr.getArgAsExpr(0);
- }
-
- // Create the vector type.
- QualType T = S.BuildExtVectorType(CurType, sizeExpr, Attr.getLoc());
+ Expr *SizeExpr = Attr.getArgAsExpr(0);
+ QualType T = S.BuildExtVectorType(CurType, SizeExpr, Attr.getLoc());
if (!T.isNull())
CurType = T;
}
@@ -7686,6 +7727,22 @@ static bool isPermittedNeonBaseType(QualType &Ty,
BTy->getKind() == BuiltinType::BFloat16;
}
+static bool verifyValidIntegerConstantExpr(Sema &S, const ParsedAttr &Attr,
+ llvm::APSInt &Result) {
+ const auto *AttrExpr = Attr.getArgAsExpr(0);
+ if (!AttrExpr->isTypeDependent() && !AttrExpr->isValueDependent()) {
+ if (Optional<llvm::APSInt> Res =
+ AttrExpr->getIntegerConstantExpr(S.Context)) {
+ Result = *Res;
+ return true;
+ }
+ }
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr << AANT_ArgumentIntegerConstant << AttrExpr->getSourceRange();
+ Attr.setInvalid();
+ return false;
+}
+
/// HandleNeonVectorTypeAttr - The "neon_vector_type" and
/// "neon_polyvector_type" attributes are used to create vector types that
/// are mangled according to ARM's ABI. Otherwise, these types are identical
@@ -7699,7 +7756,8 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
// not to need a separate attribute)
if (!S.Context.getTargetInfo().hasFeature("neon") &&
!S.Context.getTargetInfo().hasFeature("mve")) {
- S.Diag(Attr.getLoc(), diag::err_attribute_unsupported) << Attr;
+ S.Diag(Attr.getLoc(), diag::err_attribute_unsupported)
+ << Attr << "'neon' or 'mve'";
Attr.setInvalid();
return;
}
@@ -7711,16 +7769,10 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
return;
}
// The number of elements must be an ICE.
- Expr *numEltsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
llvm::APSInt numEltsInt(32);
- if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() ||
- !numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr << AANT_ArgumentIntegerConstant
- << numEltsExpr->getSourceRange();
- Attr.setInvalid();
+ if (!verifyValidIntegerConstantExpr(S, Attr, numEltsInt))
return;
- }
+
// Only certain element types are supported for Neon vectors.
if (!isPermittedNeonBaseType(CurType, VecKind, S)) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
@@ -7741,6 +7793,71 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
CurType = S.Context.getVectorType(CurType, numElts, VecKind);
}
+/// HandleArmSveVectorBitsTypeAttr - The "arm_sve_vector_bits" attribute is
+/// used to create fixed-length versions of sizeless SVE types defined by
+/// the ACLE, such as svint32_t and svbool_t.
+static void HandleArmSveVectorBitsTypeAttr(QualType &CurType, ParsedAttr &Attr,
+ Sema &S) {
+ // Target must have SVE.
+ if (!S.Context.getTargetInfo().hasFeature("sve")) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_unsupported) << Attr << "'sve'";
+ Attr.setInvalid();
+ return;
+ }
+
+ // Attribute is unsupported if '-msve-vector-bits=<bits>' isn't specified.
+ if (!S.getLangOpts().ArmSveVectorBits) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_arm_feature_sve_bits_unsupported)
+ << Attr;
+ Attr.setInvalid();
+ return;
+ }
+
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr << 1;
+ Attr.setInvalid();
+ return;
+ }
+
+ // The vector size must be an integer constant expression.
+ llvm::APSInt SveVectorSizeInBits(32);
+ if (!verifyValidIntegerConstantExpr(S, Attr, SveVectorSizeInBits))
+ return;
+
+ unsigned VecSize = static_cast<unsigned>(SveVectorSizeInBits.getZExtValue());
+
+ // The attribute vector size must match -msve-vector-bits.
+ if (VecSize != S.getLangOpts().ArmSveVectorBits) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_bad_sve_vector_size)
+ << VecSize << S.getLangOpts().ArmSveVectorBits;
+ Attr.setInvalid();
+ return;
+ }
+
+ // Attribute can only be attached to a single SVE vector or predicate type.
+ if (!CurType->isVLSTBuiltinType()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_invalid_sve_type)
+ << Attr << CurType;
+ Attr.setInvalid();
+ return;
+ }
+
+ const auto *BT = CurType->castAs<BuiltinType>();
+
+ QualType EltType = CurType->getSveEltType(S.Context);
+ unsigned TypeSize = S.Context.getTypeSize(EltType);
+ VectorType::VectorKind VecKind = VectorType::SveFixedLengthDataVector;
+ if (BT->getKind() == BuiltinType::SveBool) {
+ // Predicates are represented as i8.
+ VecSize /= S.Context.getCharWidth() * S.Context.getCharWidth();
+ VecKind = VectorType::SveFixedLengthPredicateVector;
+ } else
+ VecSize /= TypeSize;
+ CurType = S.Context.getVectorType(EltType, VecSize, VecKind);
+}
+
static void HandleArmMveStrictPolymorphismAttr(TypeProcessingState &State,
QualType &CurType,
ParsedAttr &Attr) {
@@ -7808,7 +7925,7 @@ static void HandleOpenCLAccessAttr(QualType &CurType, const ParsedAttr &Attr,
diag::note_opencl_typedef_access_qualifier) << PrevAccessQual;
} else if (CurType->isPipeType()) {
if (Attr.getSemanticSpelling() == OpenCLAccessAttr::Keyword_write_only) {
- QualType ElemType = CurType->getAs<PipeType>()->getElementType();
+ QualType ElemType = CurType->castAs<PipeType>()->getElementType();
CurType = S.Context.getWritePipeType(ElemType);
}
}
@@ -7828,49 +7945,8 @@ static void HandleMatrixTypeAttr(QualType &CurType, const ParsedAttr &Attr,
return;
}
- Expr *RowsExpr = nullptr;
- Expr *ColsExpr = nullptr;
-
- // TODO: Refactor parameter extraction into separate function
- // Get the number of rows
- if (Attr.isArgIdent(0)) {
- CXXScopeSpec SS;
- SourceLocation TemplateKeywordLoc;
- UnqualifiedId id;
- id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
- ExprResult Rows = S.ActOnIdExpression(S.getCurScope(), SS,
- TemplateKeywordLoc, id, false, false);
-
- if (Rows.isInvalid())
- // TODO: maybe a good error message would be nice here
- return;
- RowsExpr = Rows.get();
- } else {
- assert(Attr.isArgExpr(0) &&
- "Argument to should either be an identity or expression");
- RowsExpr = Attr.getArgAsExpr(0);
- }
-
- // Get the number of columns
- if (Attr.isArgIdent(1)) {
- CXXScopeSpec SS;
- SourceLocation TemplateKeywordLoc;
- UnqualifiedId id;
- id.setIdentifier(Attr.getArgAsIdent(1)->Ident, Attr.getLoc());
- ExprResult Columns = S.ActOnIdExpression(
- S.getCurScope(), SS, TemplateKeywordLoc, id, false, false);
-
- if (Columns.isInvalid())
- // TODO: a good error message would be nice here
- return;
- RowsExpr = Columns.get();
- } else {
- assert(Attr.isArgExpr(1) &&
- "Argument to should either be an identity or expression");
- ColsExpr = Attr.getArgAsExpr(1);
- }
-
- // Create the matrix type.
+ Expr *RowsExpr = Attr.getArgAsExpr(0);
+ Expr *ColsExpr = Attr.getArgAsExpr(1);
QualType T = S.BuildMatrixType(CurType, RowsExpr, ColsExpr, Attr.getLoc());
if (!T.isNull())
CurType = T;
@@ -7894,6 +7970,8 @@ static bool isAddressSpaceKind(const ParsedAttr &attr) {
return attrKind == ParsedAttr::AT_AddressSpace ||
attrKind == ParsedAttr::AT_OpenCLPrivateAddressSpace ||
attrKind == ParsedAttr::AT_OpenCLGlobalAddressSpace ||
+ attrKind == ParsedAttr::AT_OpenCLGlobalDeviceAddressSpace ||
+ attrKind == ParsedAttr::AT_OpenCLGlobalHostAddressSpace ||
attrKind == ParsedAttr::AT_OpenCLLocalAddressSpace ||
attrKind == ParsedAttr::AT_OpenCLConstantAddressSpace ||
attrKind == ParsedAttr::AT_OpenCLGenericAddressSpace;
@@ -7961,7 +8039,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk)
state.getSema().Diag(attr.getLoc(),
diag::warn_unknown_attribute_ignored)
- << attr;
+ << attr << attr.getRange();
break;
case ParsedAttr::IgnoredAttribute:
@@ -7974,6 +8052,8 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
break;
case ParsedAttr::AT_OpenCLPrivateAddressSpace:
case ParsedAttr::AT_OpenCLGlobalAddressSpace:
+ case ParsedAttr::AT_OpenCLGlobalDeviceAddressSpace:
+ case ParsedAttr::AT_OpenCLGlobalHostAddressSpace:
case ParsedAttr::AT_OpenCLLocalAddressSpace:
case ParsedAttr::AT_OpenCLConstantAddressSpace:
case ParsedAttr::AT_OpenCLGenericAddressSpace:
@@ -8004,6 +8084,10 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
VectorType::NeonPolyVector);
attr.setUsedAsTypeAttr();
break;
+ case ParsedAttr::AT_ArmSveVectorBits:
+ HandleArmSveVectorBitsTypeAttr(type, attr, state.getSema());
+ attr.setUsedAsTypeAttr();
+ break;
case ParsedAttr::AT_ArmMveStrictPolymorphism: {
HandleArmMveStrictPolymorphismAttr(state, type, attr);
attr.setUsedAsTypeAttr();
@@ -8192,6 +8276,20 @@ void Sema::completeExprArrayBound(Expr *E) {
}
}
+QualType Sema::getCompletedType(Expr *E) {
+ // Incomplete array types may be completed by the initializer attached to
+ // their definitions. For static data members of class templates and for
+ // variable templates, we need to instantiate the definition to get this
+ // initializer and complete the type.
+ if (E->getType()->isIncompleteArrayType())
+ completeExprArrayBound(E);
+
+ // FIXME: Are there other cases which require instantiating something other
+ // than the type to complete the type of an expression?
+
+ return E->getType();
+}
+
/// Ensure that the type of the given expression is complete.
///
/// This routine checks whether the expression \p E has a complete type. If the
@@ -8209,21 +8307,8 @@ void Sema::completeExprArrayBound(Expr *E) {
/// otherwise.
bool Sema::RequireCompleteExprType(Expr *E, CompleteTypeKind Kind,
TypeDiagnoser &Diagnoser) {
- QualType T = E->getType();
-
- // Incomplete array types may be completed by the initializer attached to
- // their definitions. For static data members of class templates and for
- // variable templates, we need to instantiate the definition to get this
- // initializer and complete the type.
- if (T->isIncompleteArrayType()) {
- completeExprArrayBound(E);
- T = E->getType();
- }
-
- // FIXME: Are there other cases which require instantiating something other
- // than the type to complete the type of an expression?
-
- return RequireCompleteType(E->getExprLoc(), T, Kind, Diagnoser);
+ return RequireCompleteType(E->getExprLoc(), getCompletedType(E), Kind,
+ Diagnoser);
}
bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) {
@@ -8747,7 +8832,17 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) {
// C++11 [dcl.type.simple]p4:
// The type denoted by decltype(e) is defined as follows:
- //
+
+ // C++20:
+ // - if E is an unparenthesized id-expression naming a non-type
+ // template-parameter (13.2), decltype(E) is the type of the
+ // template-parameter after performing any necessary type deduction
+ // Note that this does not pick up the implicit 'const' for a template
+ // parameter object. This rule makes no difference before C++20 so we apply
+ // it unconditionally.
+ if (const auto *SNTTPE = dyn_cast<SubstNonTypeTemplateParmExpr>(E))
+ return SNTTPE->getParameterType(S.Context);
+
// - if e is an unparenthesized id-expression or an unparenthesized class
// member access (5.2.5), decltype(e) is the type of the entity named
// by e. If there is no such entity, or if e names a set of overloaded
@@ -8756,6 +8851,8 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) {
// We apply the same rules for Objective-C ivar and property references.
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
const ValueDecl *VD = DRE->getDecl();
+ if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(VD))
+ return TPO->getType().getUnqualifiedType();
return VD->getType();
} else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
if (const ValueDecl *VD = ME->getMemberDecl())
@@ -8813,9 +8910,11 @@ QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc,
assert(!E->hasPlaceholderType() && "unexpected placeholder");
if (AsUnevaluated && CodeSynthesisContexts.empty() &&
- E->HasSideEffects(Context, false)) {
+ !E->isInstantiationDependent() && E->HasSideEffects(Context, false)) {
// The expression operand for decltype is in an unevaluated expression
// context, so side effects could result in unintended consequences.
+ // Exclude instantiation-dependent expressions, because 'decltype' is often
+ // used to build SFINAE gadgets.
Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
}
@@ -8842,7 +8941,7 @@ QualType Sema::BuildUnaryTransformType(QualType BaseType,
return QualType();
}
- EnumDecl *ED = BaseType->getAs<EnumType>()->getDecl();
+ EnumDecl *ED = BaseType->castAs<EnumType>()->getDecl();
assert(ED && "EnumType has no EnumDecl");
DiagnoseUseOfDecl(ED, Loc);
@@ -8880,11 +8979,8 @@ QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) {
else if (!T.isTriviallyCopyableType(Context))
// Some other non-trivially-copyable type (probably a C++ class)
DisallowedKind = 7;
- else if (auto *ExtTy = T->getAs<ExtIntType>()) {
- if (ExtTy->getNumBits() < 8)
+ else if (T->isExtIntType()) {
DisallowedKind = 8;
- else if (!llvm::isPowerOf2_32(ExtTy->getNumBits()))
- DisallowedKind = 9;
}
if (DisallowedKind != -1) {
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index ae0e9f1119b4..0a596e50658b 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -28,6 +28,7 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtOpenMP.h"
+#include "clang/Basic/DiagnosticParse.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Sema/Designator.h"
#include "clang/Sema/Lookup.h"
@@ -730,10 +731,11 @@ public:
#define ABSTRACT_STMT(Stmt)
#include "clang/AST/StmtNodes.inc"
-#define OMP_CLAUSE_CLASS(Enum, Str, Class) \
- LLVM_ATTRIBUTE_NOINLINE \
- OMPClause *Transform ## Class(Class *S);
-#include "llvm/Frontend/OpenMP/OMPKinds.def"
+#define GEN_CLANG_CLAUSE_CLASS
+#define CLAUSE_CLASS(Enum, Str, Class) \
+ LLVM_ATTRIBUTE_NOINLINE \
+ OMPClause *Transform##Class(Class *S);
+#include "llvm/Frontend/OpenMP/OMP.inc"
/// Build a new qualified type given its unqualified type and type location.
///
@@ -1304,7 +1306,7 @@ public:
return SemaRef.ActOnLabelStmt(IdentLoc, L, ColonLoc, SubStmt);
}
- /// Build a new label statement.
+ /// Build a new attributed statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1319,19 +1321,23 @@ public:
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
StmtResult RebuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
- Sema::ConditionResult Cond, Stmt *Init, Stmt *Then,
+ SourceLocation LParenLoc, Sema::ConditionResult Cond,
+ SourceLocation RParenLoc, Stmt *Init, Stmt *Then,
SourceLocation ElseLoc, Stmt *Else) {
- return getSema().ActOnIfStmt(IfLoc, IsConstexpr, Init, Cond, Then,
- ElseLoc, Else);
+ return getSema().ActOnIfStmt(IfLoc, IsConstexpr, LParenLoc, Init, Cond,
+ RParenLoc, Then, ElseLoc, Else);
}
/// Start building a new switch statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- StmtResult RebuildSwitchStmtStart(SourceLocation SwitchLoc, Stmt *Init,
- Sema::ConditionResult Cond) {
- return getSema().ActOnStartOfSwitchStmt(SwitchLoc, Init, Cond);
+ StmtResult RebuildSwitchStmtStart(SourceLocation SwitchLoc,
+ SourceLocation LParenLoc, Stmt *Init,
+ Sema::ConditionResult Cond,
+ SourceLocation RParenLoc) {
+ return getSema().ActOnStartOfSwitchStmt(SwitchLoc, LParenLoc, Init, Cond,
+ RParenLoc);
}
/// Attach the body to the switch statement.
@@ -2006,26 +2012,32 @@ public:
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OMPClause *RebuildOMPToClause(ArrayRef<Expr *> VarList,
- CXXScopeSpec &MapperIdScopeSpec,
- DeclarationNameInfo &MapperId,
- const OMPVarListLocTy &Locs,
- ArrayRef<Expr *> UnresolvedMappers) {
- return getSema().ActOnOpenMPToClause(VarList, MapperIdScopeSpec, MapperId,
- Locs, UnresolvedMappers);
+ OMPClause *
+ RebuildOMPToClause(ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
+ ArrayRef<SourceLocation> MotionModifiersLoc,
+ CXXScopeSpec &MapperIdScopeSpec,
+ DeclarationNameInfo &MapperId, SourceLocation ColonLoc,
+ ArrayRef<Expr *> VarList, const OMPVarListLocTy &Locs,
+ ArrayRef<Expr *> UnresolvedMappers) {
+ return getSema().ActOnOpenMPToClause(MotionModifiers, MotionModifiersLoc,
+ MapperIdScopeSpec, MapperId, ColonLoc,
+ VarList, Locs, UnresolvedMappers);
}
/// Build a new OpenMP 'from' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OMPClause *RebuildOMPFromClause(ArrayRef<Expr *> VarList,
- CXXScopeSpec &MapperIdScopeSpec,
- DeclarationNameInfo &MapperId,
- const OMPVarListLocTy &Locs,
- ArrayRef<Expr *> UnresolvedMappers) {
- return getSema().ActOnOpenMPFromClause(VarList, MapperIdScopeSpec, MapperId,
- Locs, UnresolvedMappers);
+ OMPClause *
+ RebuildOMPFromClause(ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
+ ArrayRef<SourceLocation> MotionModifiersLoc,
+ CXXScopeSpec &MapperIdScopeSpec,
+ DeclarationNameInfo &MapperId, SourceLocation ColonLoc,
+ ArrayRef<Expr *> VarList, const OMPVarListLocTy &Locs,
+ ArrayRef<Expr *> UnresolvedMappers) {
+ return getSema().ActOnOpenMPFromClause(
+ MotionModifiers, MotionModifiersLoc, MapperIdScopeSpec, MapperId,
+ ColonLoc, VarList, Locs, UnresolvedMappers);
}
/// Build a new OpenMP 'use_device_ptr' clause.
@@ -3500,7 +3512,8 @@ public:
// Build the CallExpr
ExprResult TheCall = CallExpr::Create(
SemaRef.Context, Callee, SubExprs, Builtin->getCallResultType(),
- Expr::getValueKindForType(Builtin->getReturnType()), RParenLoc);
+ Expr::getValueKindForType(Builtin->getReturnType()), RParenLoc,
+ FPOptionsOverride());
// Type-check the __builtin_shufflevector expression.
return SemaRef.SemaBuiltinShuffleVector(cast<CallExpr>(TheCall.get()));
@@ -3534,12 +3547,12 @@ public:
}
case TemplateArgument::Template:
- return TemplateArgumentLoc(TemplateArgument(
- Pattern.getArgument().getAsTemplate(),
- NumExpansions),
- Pattern.getTemplateQualifierLoc(),
- Pattern.getTemplateNameLoc(),
- EllipsisLoc);
+ return TemplateArgumentLoc(
+ SemaRef.Context,
+ TemplateArgument(Pattern.getArgument().getAsTemplate(),
+ NumExpansions),
+ Pattern.getTemplateQualifierLoc(), Pattern.getTemplateNameLoc(),
+ EllipsisLoc);
case TemplateArgument::Null:
case TemplateArgument::Integral:
@@ -3576,13 +3589,15 @@ public:
///
/// By default, performs semantic analysis in order to build a new fold
/// expression.
- ExprResult RebuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS,
+ ExprResult RebuildCXXFoldExpr(UnresolvedLookupExpr *ULE,
+ SourceLocation LParenLoc, Expr *LHS,
BinaryOperatorKind Operator,
SourceLocation EllipsisLoc, Expr *RHS,
SourceLocation RParenLoc,
Optional<unsigned> NumExpansions) {
- return getSema().BuildCXXFoldExpr(LParenLoc, LHS, Operator, EllipsisLoc,
- RHS, RParenLoc, NumExpansions);
+ return getSema().BuildCXXFoldExpr(ULE, LParenLoc, LHS, Operator,
+ EllipsisLoc, RHS, RParenLoc,
+ NumExpansions);
}
/// Build an empty C++1z fold-expression with the given operator.
@@ -3609,8 +3624,8 @@ public:
}
ExprResult RebuildRecoveryExpr(SourceLocation BeginLoc, SourceLocation EndLoc,
- ArrayRef<Expr *> SubExprs) {
- return getSema().CreateRecoveryExpr(BeginLoc, EndLoc, SubExprs);
+ ArrayRef<Expr *> SubExprs, QualType Type) {
+ return getSema().CreateRecoveryExpr(BeginLoc, EndLoc, SubExprs, Type);
}
private:
@@ -3677,10 +3692,11 @@ OMPClause *TreeTransform<Derived>::TransformOMPClause(OMPClause *S) {
switch (S->getClauseKind()) {
default: break;
// Transform individual clause nodes
-#define OMP_CLAUSE_CLASS(Enum, Str, Class) \
+#define GEN_CLANG_CLAUSE_CLASS
+#define CLAUSE_CLASS(Enum, Str, Class) \
case Enum: \
- return getDerived().Transform ## Class(cast<Class>(S));
-#include "llvm/Frontend/OpenMP/OMPKinds.def"
+ return getDerived().Transform##Class(cast<Class>(S));
+#include "llvm/Frontend/OpenMP/OMP.inc"
}
return S;
@@ -4275,8 +4291,8 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
if (Template.isNull())
return true;
- Output = TemplateArgumentLoc(TemplateArgument(Template), QualifierLoc,
- Input.getTemplateNameLoc());
+ Output = TemplateArgumentLoc(SemaRef.Context, TemplateArgument(Template),
+ QualifierLoc, Input.getTemplateNameLoc());
return false;
}
@@ -5162,7 +5178,7 @@ template <typename Derived>
QualType TreeTransform<Derived>::TransformDependentVectorType(
TypeLocBuilder &TLB, DependentVectorTypeLoc TL) {
const DependentVectorType *T = TL.getTypePtr();
- QualType ElementType = getDerived().TransformType(T->getElementType());
+ QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
if (ElementType.isNull())
return QualType();
@@ -5203,7 +5219,7 @@ QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
const DependentSizedExtVectorType *T = TL.getTypePtr();
// FIXME: ext vector locs should be nested
- QualType ElementType = getDerived().TransformType(T->getElementType());
+ QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
if (ElementType.isNull())
return QualType();
@@ -5370,7 +5386,7 @@ template <typename Derived>
QualType TreeTransform<Derived>::TransformVectorType(TypeLocBuilder &TLB,
VectorTypeLoc TL) {
const VectorType *T = TL.getTypePtr();
- QualType ElementType = getDerived().TransformType(T->getElementType());
+ QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
if (ElementType.isNull())
return QualType();
@@ -5393,7 +5409,7 @@ template<typename Derived>
QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB,
ExtVectorTypeLoc TL) {
const VectorType *T = TL.getTypePtr();
- QualType ElementType = getDerived().TransformType(T->getElementType());
+ QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
if (ElementType.isNull())
return QualType();
@@ -5465,6 +5481,7 @@ ParmVarDecl *TreeTransform<Derived>::TransformFunctionTypeParam(
/* DefArg */ nullptr);
newParm->setScopeInfo(OldParm->getFunctionScopeDepth(),
OldParm->getFunctionScopeIndex() + indexAdjustment);
+ transformedLocalDecl(OldParm, {newParm});
return newParm;
}
@@ -7280,9 +7297,9 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
Else.get() == S->getElse())
return S;
- return getDerived().RebuildIfStmt(S->getIfLoc(), S->isConstexpr(), Cond,
- Init.get(), Then.get(), S->getElseLoc(),
- Else.get());
+ return getDerived().RebuildIfStmt(
+ S->getIfLoc(), S->isConstexpr(), S->getLParenLoc(), Cond,
+ S->getRParenLoc(), Init.get(), Then.get(), S->getElseLoc(), Else.get());
}
template<typename Derived>
@@ -7301,8 +7318,9 @@ TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) {
return StmtError();
// Rebuild the switch statement.
- StmtResult Switch
- = getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(), Init.get(), Cond);
+ StmtResult Switch =
+ getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(), S->getLParenLoc(),
+ Init.get(), Cond, S->getRParenLoc());
if (Switch.isInvalid())
return StmtError();
@@ -8323,7 +8341,14 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective(
StmtResult Body;
{
Sema::CompoundScopeRAII CompoundScope(getSema());
- Stmt *CS = D->getInnermostCapturedStmt()->getCapturedStmt();
+ Stmt *CS;
+ if (D->getDirectiveKind() == OMPD_atomic ||
+ D->getDirectiveKind() == OMPD_critical ||
+ D->getDirectiveKind() == OMPD_section ||
+ D->getDirectiveKind() == OMPD_master)
+ CS = D->getAssociatedStmt();
+ else
+ CS = D->getInnermostCapturedStmt()->getCapturedStmt();
Body = getDerived().TransformStmt(CS);
}
AssociatedStmt =
@@ -9737,8 +9762,9 @@ OMPClause *TreeTransform<Derived>::TransformOMPToClause(OMPToClause *C) {
if (transformOMPMappableExprListClause<Derived, OMPToClause>(
*this, C, Vars, MapperIdScopeSpec, MapperIdInfo, UnresolvedMappers))
return nullptr;
- return getDerived().RebuildOMPToClause(Vars, MapperIdScopeSpec, MapperIdInfo,
- Locs, UnresolvedMappers);
+ return getDerived().RebuildOMPToClause(
+ C->getMotionModifiers(), C->getMotionModifiersLoc(), MapperIdScopeSpec,
+ MapperIdInfo, C->getColonLoc(), Vars, Locs, UnresolvedMappers);
}
template <typename Derived>
@@ -9752,7 +9778,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPFromClause(OMPFromClause *C) {
*this, C, Vars, MapperIdScopeSpec, MapperIdInfo, UnresolvedMappers))
return nullptr;
return getDerived().RebuildOMPFromClause(
- Vars, MapperIdScopeSpec, MapperIdInfo, Locs, UnresolvedMappers);
+ C->getMotionModifiers(), C->getMotionModifiersLoc(), MapperIdScopeSpec,
+ MapperIdInfo, C->getColonLoc(), Vars, Locs, UnresolvedMappers);
}
template <typename Derived>
@@ -10198,7 +10225,7 @@ ExprResult TreeTransform<Derived>::TransformRecoveryExpr(RecoveryExpr *E) {
if (!getDerived().AlwaysRebuild() && !Changed)
return E;
return getDerived().RebuildRecoveryExpr(E->getBeginLoc(), E->getEndLoc(),
- Children);
+ Children, E->getType());
}
template<typename Derived>
@@ -10466,6 +10493,15 @@ TreeTransform<Derived>::TransformCallExpr(CallExpr *E) {
// FIXME: Wrong source location information for the '('.
SourceLocation FakeLParenLoc
= ((Expr *)Callee.get())->getSourceRange().getBegin();
+
+ Sema::FPFeaturesStateRAII FPFeaturesState(getSema());
+ if (E->hasStoredFPFeatures()) {
+ FPOptionsOverride NewOverrides = E->getFPFeatures();
+ getSema().CurFPFeatures =
+ NewOverrides.applyOverrides(getSema().getLangOpts());
+ getSema().FpPragmaStack.CurrentValue = NewOverrides;
+ }
+
return getDerived().RebuildCallExpr(Callee.get(), FakeLParenLoc,
Args,
E->getRParenLoc());
@@ -10580,7 +10616,7 @@ TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) {
FPOptionsOverride NewOverrides(E->getFPFeatures(getSema().getLangOpts()));
getSema().CurFPFeatures =
NewOverrides.applyOverrides(getSema().getLangOpts());
- getSema().FpPragmaStack.CurrentValue = NewOverrides.getAsOpaqueInt();
+ getSema().FpPragmaStack.CurrentValue = NewOverrides;
return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(),
LHS.get(), RHS.get());
}
@@ -10637,7 +10673,7 @@ TreeTransform<Derived>::TransformCompoundAssignOperator(
FPOptionsOverride NewOverrides(E->getFPFeatures(getSema().getLangOpts()));
getSema().CurFPFeatures =
NewOverrides.applyOverrides(getSema().getLangOpts());
- getSema().FpPragmaStack.CurrentValue = NewOverrides.getAsOpaqueInt();
+ getSema().FpPragmaStack.CurrentValue = NewOverrides;
return getDerived().TransformBinaryOperator(E);
}
@@ -11115,7 +11151,7 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
FPOptionsOverride NewOverrides(E->getFPFeatures());
getSema().CurFPFeatures =
NewOverrides.applyOverrides(getSema().getLangOpts());
- getSema().FpPragmaStack.CurrentValue = NewOverrides.getAsOpaqueInt();
+ getSema().FpPragmaStack.CurrentValue = NewOverrides;
return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(),
E->getOperatorLoc(),
@@ -12711,12 +12747,12 @@ TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr(
bool ArgumentChanged = false;
SmallVector<Expr*, 8> Args;
- Args.reserve(E->arg_size());
+ Args.reserve(E->getNumArgs());
{
EnterExpressionEvaluationContext Context(
getSema(), EnterExpressionEvaluationContext::InitList,
E->isListInitialization());
- if (getDerived().TransformExprs(E->arg_begin(), E->arg_size(), true, Args,
+ if (getDerived().TransformExprs(E->arg_begin(), E->getNumArgs(), true, Args,
&ArgumentChanged))
return ExprError();
}
@@ -13110,6 +13146,14 @@ TreeTransform<Derived>::TransformMaterializeTemporaryExpr(
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) {
+ UnresolvedLookupExpr *Callee = nullptr;
+ if (Expr *OldCallee = E->getCallee()) {
+ ExprResult CalleeResult = getDerived().TransformExpr(OldCallee);
+ if (CalleeResult.isInvalid())
+ return ExprError();
+ Callee = cast<UnresolvedLookupExpr>(CalleeResult.get());
+ }
+
Expr *Pattern = E->getPattern();
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
@@ -13149,8 +13193,20 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) {
return E;
return getDerived().RebuildCXXFoldExpr(
- E->getBeginLoc(), LHS.get(), E->getOperator(), E->getEllipsisLoc(),
- RHS.get(), E->getEndLoc(), NumExpansions);
+ Callee, E->getBeginLoc(), LHS.get(), E->getOperator(),
+ E->getEllipsisLoc(), RHS.get(), E->getEndLoc(), NumExpansions);
+ }
+
+ // Formally a fold expression expands to nested parenthesized expressions.
+ // Enforce this limit to avoid creating trees so deep we can't safely traverse
+ // them.
+ if (NumExpansions && SemaRef.getLangOpts().BracketDepth < NumExpansions) {
+ SemaRef.Diag(E->getEllipsisLoc(),
+ clang::diag::err_fold_expression_limit_exceeded)
+ << *NumExpansions << SemaRef.getLangOpts().BracketDepth
+ << E->getSourceRange();
+ SemaRef.Diag(E->getEllipsisLoc(), diag::note_bracket_depth);
+ return ExprError();
}
// The transform has determined that we should perform an elementwise
@@ -13170,8 +13226,8 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) {
return true;
Result = getDerived().RebuildCXXFoldExpr(
- E->getBeginLoc(), Out.get(), E->getOperator(), E->getEllipsisLoc(),
- Result.get(), E->getEndLoc(), OrigNumExpansions);
+ Callee, E->getBeginLoc(), Out.get(), E->getOperator(),
+ E->getEllipsisLoc(), Result.get(), E->getEndLoc(), OrigNumExpansions);
if (Result.isInvalid())
return true;
}
@@ -13186,16 +13242,21 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) {
if (Out.get()->containsUnexpandedParameterPack()) {
// We still have a pack; retain a pack expansion for this slice.
Result = getDerived().RebuildCXXFoldExpr(
- E->getBeginLoc(), LeftFold ? Result.get() : Out.get(),
+ Callee, E->getBeginLoc(), LeftFold ? Result.get() : Out.get(),
E->getOperator(), E->getEllipsisLoc(),
LeftFold ? Out.get() : Result.get(), E->getEndLoc(),
OrigNumExpansions);
} 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());
+ Expr *LHS = LeftFold ? Result.get() : Out.get();
+ Expr *RHS = LeftFold ? Out.get() : Result.get();
+ if (Callee)
+ Result = getDerived().RebuildCXXOperatorCallExpr(
+ BinaryOperator::getOverloadedOperator(E->getOperator()),
+ E->getEllipsisLoc(), Callee, LHS, RHS);
+ else
+ Result = getDerived().RebuildBinaryOperator(E->getEllipsisLoc(),
+ E->getOperator(), LHS, RHS);
} else
Result = Out;
@@ -13213,8 +13274,8 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) {
return true;
Result = getDerived().RebuildCXXFoldExpr(
- E->getBeginLoc(), Result.get(), E->getOperator(), E->getEllipsisLoc(),
- Out.get(), E->getEndLoc(), OrigNumExpansions);
+ Callee, E->getBeginLoc(), Result.get(), E->getOperator(),
+ E->getEllipsisLoc(), Out.get(), E->getEndLoc(), OrigNumExpansions);
if (Result.isInvalid())
return true;
}
diff --git a/clang/lib/Sema/UsedDeclVisitor.h b/clang/lib/Sema/UsedDeclVisitor.h
index d207e07f451a..c33d30478e2a 100644
--- a/clang/lib/Sema/UsedDeclVisitor.h
+++ b/clang/lib/Sema/UsedDeclVisitor.h
@@ -67,10 +67,13 @@ public:
void VisitCXXDeleteExpr(CXXDeleteExpr *E) {
if (E->getOperatorDelete())
asImpl().visitUsedDecl(E->getBeginLoc(), E->getOperatorDelete());
- QualType Destroyed = S.Context.getBaseElementType(E->getDestroyedType());
- if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
- CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl());
- asImpl().visitUsedDecl(E->getBeginLoc(), S.LookupDestructor(Record));
+ QualType DestroyedOrNull = E->getDestroyedType();
+ if (!DestroyedOrNull.isNull()) {
+ QualType Destroyed = S.Context.getBaseElementType(DestroyedOrNull);
+ if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl());
+ asImpl().visitUsedDecl(E->getBeginLoc(), S.LookupDestructor(Record));
+ }
}
Inherited::VisitCXXDeleteExpr(E);