Quuxplusone updated this revision to Diff 409740.
Quuxplusone added a comment.
Rebase and update — this is becoming more and more of a trivial patch, which I
guess is good!
Add a test case for https://github.com/llvm/llvm-project/issues/53911 (which I
finally thought to test, and was surprised to find it didn't work either before
//or// after my patch).
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D119184/new/
https://reviews.llvm.org/D119184
Files:
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaStmt.cpp
clang/test/SemaTemplate/concepts.cpp
Index: clang/test/SemaTemplate/concepts.cpp
===================================================================
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -169,3 +169,42 @@
template<C T, typename U> void f(T, U) = delete;
void g() { f(0, 0); }
}
+
+namespace PR49188 {
+ template<class T> concept C = false; // expected-note 6 {{because 'false' evaluated to false}}
+
+ C auto f1() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+ return void();
+ }
+ C auto f2() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+ return;
+ }
+ C auto f3() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+ }
+ C decltype(auto) f4() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+ return void();
+ }
+ C decltype(auto) f5() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+ return;
+ }
+ C decltype(auto) f6() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+ }
+ C auto& f7() { // expected-error {{cannot form a reference to 'void'}}
+ return void();
+ }
+ C auto& f8() {
+ return; // expected-error {{cannot deduce return type 'C auto &' from omitted return expression}}
+ }
+ C auto& f9() { // expected-error {{cannot deduce return type 'C auto &' for function with no return statements}}
+ }
+}
+namespace PR53911 {
+ template<class T> concept C = false;
+
+ C auto *f1() {
+ return (void*)nullptr; // FIXME: should error
+ }
+ C auto *f2() {
+ return (int*)nullptr; // FIXME: should error
+ }
+}
Index: clang/lib/Sema/SemaStmt.cpp
===================================================================
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -3762,8 +3762,8 @@
bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
SourceLocation ReturnLoc,
Expr *&RetExpr,
- AutoType *AT) {
- // If this is the conversion function for a lambda, we choose to deduce it
+ const AutoType *AT) {
+ // If this is the conversion function for a lambda, we choose to deduce its
// type from the corresponding call operator, not from the synthesized return
// statement within it. See Sema::DeduceReturnType.
if (isLambdaConversionOperator(FD))
@@ -3808,19 +3808,26 @@
LocalTypedefNameReferencer Referencer(*this);
Referencer.TraverseType(RetExpr->getType());
} else {
- // In the case of a return with no operand, the initializer is considered
- // to be void().
- //
- // Deduction here can only succeed if the return type is exactly 'cv auto'
- // or 'decltype(auto)', so just check for that case directly.
+ // For a function with a deduced result type to return void,
+ // the result type as written must be 'auto' or 'decltype(auto)',
+ // possibly cv-qualified or constrained, but not ref-qualified.
if (!OrigResultType.getType()->getAs<AutoType>()) {
Diag(ReturnLoc, diag::err_auto_fn_return_void_but_not_auto)
<< OrigResultType.getType();
return true;
}
- // We always deduce U = void in this case.
- Deduced = SubstAutoType(OrigResultType.getType(), Context.VoidTy);
- if (Deduced.isNull())
+ // In the case of a return with no operand, the initializer is considered
+ // to be 'void()'.
+ Expr *Dummy = new (Context) CXXScalarValueInitExpr(
+ Context.VoidTy,
+ Context.getTrivialTypeSourceInfo(Context.VoidTy, ReturnLoc), ReturnLoc);
+ DeduceAutoResult DAR = DeduceAutoType(OrigResultType, Dummy, Deduced);
+
+ if (DAR == DAR_Failed && !FD->isInvalidDecl())
+ Diag(ReturnLoc, diag::err_auto_fn_deduction_failure)
+ << OrigResultType.getType() << Dummy->getType();
+
+ if (DAR != DAR_Succeeded)
return true;
}
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -14660,18 +14660,20 @@
if (getLangOpts().CPlusPlus14) {
if (!FD->isInvalidDecl() && Body && !FD->isDependentContext() &&
FD->getReturnType()->isUndeducedType()) {
- // If the function has a deduced result type but contains no 'return'
- // statements, the result type as written must be exactly 'auto', and
- // the deduced result type is 'void'.
+ // For a function with a deduced result type to return void,
+ // the result type as written must be 'auto' or 'decltype(auto)',
+ // possibly cv-qualified or constrained, but not ref-qualified.
if (!FD->getReturnType()->getAs<AutoType>()) {
Diag(dcl->getLocation(), diag::err_auto_fn_no_return_but_not_auto)
<< FD->getReturnType();
FD->setInvalidDecl();
} else {
- // Substitute 'void' for the 'auto' in the type.
- TypeLoc ResultType = getReturnTypeLoc(FD);
- Context.adjustDeducedFunctionResultType(
- FD, SubstAutoType(ResultType.getType(), Context.VoidTy));
+ // Falling off the end of the function is the same as 'return;'.
+ Expr *Dummy = nullptr;
+ if (DeduceFunctionTypeFromReturnExpr(
+ FD, dcl->getLocation(), Dummy,
+ FD->getReturnType()->getAs<AutoType>()))
+ FD->setInvalidDecl();
}
}
} else if (getLangOpts().CPlusPlus11 && isLambdaCallOperator(FD)) {
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -8671,7 +8671,7 @@
bool DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
SourceLocation ReturnLoc,
- Expr *&RetExpr, AutoType *AT);
+ Expr *&RetExpr, const AutoType *AT);
FunctionTemplateDecl *getMoreSpecializedTemplate(
FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, SourceLocation Loc,
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits