summaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/SemaCodeComplete.cpp10
-rw-r--r--lib/Sema/SemaCoroutine.cpp35
-rw-r--r--lib/Sema/SemaDeclAttr.cpp14
-rw-r--r--lib/Sema/SemaExpr.cpp8
-rw-r--r--lib/Sema/SemaExprCXX.cpp9
-rw-r--r--lib/Sema/SemaLambda.cpp16
-rw-r--r--lib/Sema/SemaStmt.cpp58
7 files changed, 94 insertions, 56 deletions
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index b9349dc06bff..83c3bd27596c 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -4542,8 +4542,10 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
bool EnteringContext) {
if (!SS.getScopeRep() || !CodeCompleter)
return;
-
- DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
+
+ // Always pretend to enter a context to ensure that a dependent type
+ // resolves to a dependent record.
+ DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
if (!Ctx)
return;
@@ -4573,7 +4575,9 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Results.ExitScope();
CodeCompletionDeclConsumer Consumer(Results, CurContext);
- LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
+ LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
+ /*IncludeGlobalScope=*/true,
+ /*IncludeDependentBases=*/true);
HandleCodeCompleteResults(this, CodeCompleter,
Results.getCompletionContext(),
diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp
index 06ae66076e8a..b05c0998d3dd 100644
--- a/lib/Sema/SemaCoroutine.cpp
+++ b/lib/Sema/SemaCoroutine.cpp
@@ -470,11 +470,11 @@ static FunctionScopeInfo *checkCoroutineContext(Sema &S, SourceLocation Loc,
return ScopeInfo;
}
-static bool actOnCoroutineBodyStart(Sema &S, Scope *SC, SourceLocation KWLoc,
- StringRef Keyword) {
- if (!checkCoroutineContext(S, KWLoc, Keyword))
+bool Sema::ActOnCoroutineBodyStart(Scope *SC, SourceLocation KWLoc,
+ StringRef Keyword) {
+ if (!checkCoroutineContext(*this, KWLoc, Keyword))
return false;
- auto *ScopeInfo = S.getCurFunction();
+ auto *ScopeInfo = getCurFunction();
assert(ScopeInfo->CoroutinePromise);
// If we have existing coroutine statements then we have already built
@@ -484,24 +484,24 @@ static bool actOnCoroutineBodyStart(Sema &S, Scope *SC, SourceLocation KWLoc,
ScopeInfo->setNeedsCoroutineSuspends(false);
- auto *Fn = cast<FunctionDecl>(S.CurContext);
+ auto *Fn = cast<FunctionDecl>(CurContext);
SourceLocation Loc = Fn->getLocation();
// Build the initial suspend point
auto buildSuspends = [&](StringRef Name) mutable -> StmtResult {
ExprResult Suspend =
- buildPromiseCall(S, ScopeInfo->CoroutinePromise, Loc, Name, None);
+ buildPromiseCall(*this, ScopeInfo->CoroutinePromise, Loc, Name, None);
if (Suspend.isInvalid())
return StmtError();
- Suspend = buildOperatorCoawaitCall(S, SC, Loc, Suspend.get());
+ Suspend = buildOperatorCoawaitCall(*this, SC, Loc, Suspend.get());
if (Suspend.isInvalid())
return StmtError();
- Suspend = S.BuildResolvedCoawaitExpr(Loc, Suspend.get(),
- /*IsImplicit*/ true);
- Suspend = S.ActOnFinishFullExpr(Suspend.get());
+ Suspend = BuildResolvedCoawaitExpr(Loc, Suspend.get(),
+ /*IsImplicit*/ true);
+ Suspend = ActOnFinishFullExpr(Suspend.get());
if (Suspend.isInvalid()) {
- S.Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required)
+ Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required)
<< ((Name == "initial_suspend") ? 0 : 1);
- S.Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword;
+ Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword;
return StmtError();
}
return cast<Stmt>(Suspend.get());
@@ -521,7 +521,7 @@ static bool actOnCoroutineBodyStart(Sema &S, Scope *SC, SourceLocation KWLoc,
}
ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
- if (!actOnCoroutineBodyStart(*this, S, Loc, "co_await")) {
+ if (!ActOnCoroutineBodyStart(S, Loc, "co_await")) {
CorrectDelayedTyposInExpr(E);
return ExprError();
}
@@ -613,7 +613,7 @@ ExprResult Sema::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr *E,
}
ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
- if (!actOnCoroutineBodyStart(*this, S, Loc, "co_yield")) {
+ if (!ActOnCoroutineBodyStart(S, Loc, "co_yield")) {
CorrectDelayedTyposInExpr(E);
return ExprError();
}
@@ -658,14 +658,15 @@ ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
if (RSS.IsInvalid)
return ExprError();
- Expr *Res = new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1],
- RSS.Results[2], RSS.OpaqueValue);
+ Expr *Res =
+ new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1],
+ RSS.Results[2], RSS.OpaqueValue);
return Res;
}
StmtResult Sema::ActOnCoreturnStmt(Scope *S, SourceLocation Loc, Expr *E) {
- if (!actOnCoroutineBodyStart(*this, S, Loc, "co_return")) {
+ if (!ActOnCoroutineBodyStart(S, Loc, "co_return")) {
CorrectDelayedTyposInExpr(E);
return StmtError();
}
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 6c492fac9eb9..b43642f5493b 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -313,8 +313,8 @@ static bool checkAttrMutualExclusion(Sema &S, Decl *D, SourceRange Range,
/// \returns true if IdxExpr is a valid index.
template <typename AttrInfo>
static bool checkFunctionOrMethodParameterIndex(
- Sema &S, const Decl *D, const AttrInfo& Attr,
- unsigned AttrArgNum, const Expr *IdxExpr, uint64_t &Idx) {
+ Sema &S, const Decl *D, const AttrInfo &Attr, unsigned AttrArgNum,
+ const Expr *IdxExpr, uint64_t &Idx, bool AllowImplicitThis = false) {
assert(isFunctionOrMethodOrBlock(D));
// In C++ the implicit 'this' function parameter also counts.
@@ -341,7 +341,7 @@ static bool checkFunctionOrMethodParameterIndex(
return false;
}
Idx--; // Convert to zero-based.
- if (HasImplicitThisParam) {
+ if (HasImplicitThisParam && !AllowImplicitThis) {
if (Idx == 0) {
S.Diag(getAttrLoc(Attr),
diag::err_attribute_invalid_implicit_this_argument)
@@ -4604,14 +4604,16 @@ static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,
static void handleXRayLogArgsAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
uint64_t ArgCount;
+
if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 1, Attr.getArgAsExpr(0),
- ArgCount))
+ ArgCount,
+ true /* AllowImplicitThis*/))
return;
// ArgCount isn't a parameter index [0;n), it's a count [1;n] - hence + 1.
D->addAttr(::new (S.Context)
- XRayLogArgsAttr(Attr.getRange(), S.Context, ++ArgCount,
- Attr.getAttributeSpellingListIndex()));
+ XRayLogArgsAttr(Attr.getRange(), S.Context, ++ArgCount,
+ Attr.getAttributeSpellingListIndex()));
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 0f8f5c253ac6..75a6903392ea 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -12057,11 +12057,17 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
}
break;
case UO_Extension:
- case UO_Coawait:
resultType = Input.get()->getType();
VK = Input.get()->getValueKind();
OK = Input.get()->getObjectKind();
break;
+ case UO_Coawait:
+ // It's unnessesary to represent the pass-through operator co_await in the
+ // AST; just return the input expression instead.
+ assert(!Input.get()->getType()->isDependentType() &&
+ "the co_await expression must be non-dependant before "
+ "building operator co_await");
+ return Input;
}
if (resultType.isNull() || Input.isInvalid())
return ExprError();
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 00a4b39f1423..a9ff21bc41ab 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -189,12 +189,15 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
// have one) and, if that fails to find a match, in the scope (if
// we're allowed to look there).
Found.clear();
- if (Step == 0 && LookupCtx)
+ if (Step == 0 && LookupCtx) {
+ if (RequireCompleteDeclContext(SS, LookupCtx))
+ return nullptr;
LookupQualifiedName(Found, LookupCtx);
- else if (Step == 1 && LookInScope && S)
+ } else if (Step == 1 && LookInScope && S) {
LookupName(Found, S);
- else
+ } else {
continue;
+ }
// FIXME: Should we be suppressing ambiguities here?
if (Found.isAmbiguous())
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index a6239283b47b..d6b70610d461 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -1492,6 +1492,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
bool ExplicitResultType;
CleanupInfo LambdaCleanup;
bool ContainsUnexpandedParameterPack;
+ bool IsGenericLambda;
{
CallOperator = LSI->CallOperator;
Class = LSI->Lambda;
@@ -1500,7 +1501,8 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
ExplicitResultType = !LSI->HasImplicitReturnType;
LambdaCleanup = LSI->Cleanup;
ContainsUnexpandedParameterPack = LSI->ContainsUnexpandedParameterPack;
-
+ IsGenericLambda = Class->isGenericLambda();
+
CallOperator->setLexicalDeclContext(Class);
Decl *TemplateOrNonTemplateCallOperatorDecl =
CallOperator->getDescribedFunctionTemplate()
@@ -1520,8 +1522,13 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
bool IsImplicit = I >= LSI->NumExplicitCaptures;
// Warn about unused explicit captures.
- if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed())
- DiagnoseUnusedLambdaCapture(From);
+ if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed()) {
+ // Initialized captures that are non-ODR used may not be eliminated.
+ bool NonODRUsedInitCapture =
+ IsGenericLambda && From.isNonODRUsed() && From.getInitExpr();
+ if (!NonODRUsedInitCapture)
+ DiagnoseUnusedLambdaCapture(From);
+ }
// Handle 'this' capture.
if (From.isThisCapture()) {
@@ -1568,8 +1575,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
// same parameter and return types as the closure type's function call
// operator.
// FIXME: Fix generic lambda to block conversions.
- if (getLangOpts().Blocks && getLangOpts().ObjC1 &&
- !Class->isGenericLambda())
+ if (getLangOpts().Blocks && getLangOpts().ObjC1 && !IsGenericLambda)
addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator);
// Finalize the lambda class.
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 151b89ab8d2a..eed10b077eb8 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -1989,11 +1989,11 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
return StmtError();
}
- // Coroutines: 'for co_await' implicitly co_awaits its range.
- if (CoawaitLoc.isValid()) {
- ExprResult Coawait = ActOnCoawaitExpr(S, CoawaitLoc, Range);
- if (Coawait.isInvalid()) return StmtError();
- Range = Coawait.get();
+ // Build the coroutine state immediately and not later during template
+ // instantiation
+ if (!CoawaitLoc.isInvalid()) {
+ if (!ActOnCoroutineBodyStart(S, CoawaitLoc, "co_await"))
+ return StmtError();
}
// Build auto && __range = range-init
@@ -2031,16 +2031,12 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
/// BeginExpr and EndExpr are set and FRS_Success is returned on success;
/// CandidateSet and BEF are set and some non-success value is returned on
/// failure.
-static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef,
- Expr *BeginRange, Expr *EndRange,
- QualType RangeType,
- VarDecl *BeginVar,
- VarDecl *EndVar,
- SourceLocation ColonLoc,
- OverloadCandidateSet *CandidateSet,
- ExprResult *BeginExpr,
- ExprResult *EndExpr,
- BeginEndFunction *BEF) {
+static Sema::ForRangeStatus
+BuildNonArrayForRange(Sema &SemaRef, Expr *BeginRange, Expr *EndRange,
+ QualType RangeType, VarDecl *BeginVar, VarDecl *EndVar,
+ SourceLocation ColonLoc, SourceLocation CoawaitLoc,
+ OverloadCandidateSet *CandidateSet, ExprResult *BeginExpr,
+ ExprResult *EndExpr, BeginEndFunction *BEF) {
DeclarationNameInfo BeginNameInfo(
&SemaRef.PP.getIdentifierTable().get("begin"), ColonLoc);
DeclarationNameInfo EndNameInfo(&SemaRef.PP.getIdentifierTable().get("end"),
@@ -2087,6 +2083,15 @@ static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef,
<< ColonLoc << BEF_begin << BeginRange->getType();
return RangeStatus;
}
+ if (!CoawaitLoc.isInvalid()) {
+ // FIXME: getCurScope() should not be used during template instantiation.
+ // We should pick up the set of unqualified lookup results for operator
+ // co_await during the initial parse.
+ *BeginExpr = SemaRef.ActOnCoawaitExpr(SemaRef.getCurScope(), ColonLoc,
+ BeginExpr->get());
+ if (BeginExpr->isInvalid())
+ return Sema::FRS_DiagnosticIssued;
+ }
if (FinishForRangeVarDecl(SemaRef, BeginVar, BeginExpr->get(), ColonLoc,
diag::err_for_range_iter_deduction_failure)) {
NoteForRangeBeginEndFunction(SemaRef, BeginExpr->get(), *BEF);
@@ -2206,8 +2211,12 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
// Deduce any 'auto's in the loop variable as 'DependentTy'. We'll fill
// them in properly when we instantiate the loop.
- if (!LoopVar->isInvalidDecl() && Kind != BFRK_Check)
+ if (!LoopVar->isInvalidDecl() && Kind != BFRK_Check) {
+ if (auto *DD = dyn_cast<DecompositionDecl>(LoopVar))
+ for (auto *Binding : DD->bindings())
+ Binding->setType(Context.DependentTy);
LoopVar->setType(SubstAutoType(LoopVar->getType(), Context.DependentTy));
+ }
} else if (!BeginDeclStmt.get()) {
SourceLocation RangeLoc = RangeVar->getLocation();
@@ -2249,6 +2258,11 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
// begin-expr is __range.
BeginExpr = BeginRangeRef;
+ if (!CoawaitLoc.isInvalid()) {
+ BeginExpr = ActOnCoawaitExpr(S, ColonLoc, BeginExpr.get());
+ if (BeginExpr.isInvalid())
+ return StmtError();
+ }
if (FinishForRangeVarDecl(*this, BeginVar, BeginRangeRef.get(), ColonLoc,
diag::err_for_range_iter_deduction_failure)) {
NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
@@ -2331,11 +2345,10 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
OverloadCandidateSet CandidateSet(RangeLoc,
OverloadCandidateSet::CSK_Normal);
BeginEndFunction BEFFailure;
- ForRangeStatus RangeStatus =
- BuildNonArrayForRange(*this, BeginRangeRef.get(),
- EndRangeRef.get(), RangeType,
- BeginVar, EndVar, ColonLoc, &CandidateSet,
- &BeginExpr, &EndExpr, &BEFFailure);
+ ForRangeStatus RangeStatus = BuildNonArrayForRange(
+ *this, BeginRangeRef.get(), EndRangeRef.get(), RangeType, BeginVar,
+ EndVar, ColonLoc, CoawaitLoc, &CandidateSet, &BeginExpr, &EndExpr,
+ &BEFFailure);
if (Kind == BFRK_Build && RangeStatus == FRS_NoViableFunction &&
BEFFailure == BEF_begin) {
@@ -2432,6 +2445,9 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
IncrExpr = ActOnUnaryOp(S, ColonLoc, tok::plusplus, BeginRef.get());
if (!IncrExpr.isInvalid() && CoawaitLoc.isValid())
+ // FIXME: getCurScope() should not be used during template instantiation.
+ // We should pick up the set of unqualified lookup results for operator
+ // co_await during the initial parse.
IncrExpr = ActOnCoawaitExpr(S, CoawaitLoc, IncrExpr.get());
if (!IncrExpr.isInvalid())
IncrExpr = ActOnFinishFullExpr(IncrExpr.get());