[clang] 282cae0 - [Sema] Fix crash on __fp16 parameters in template instantiations

Ilya Biryukov via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 21 06:09:31 PDT 2023


Author: Ilya Biryukov
Date: 2023-03-21T14:06:46+01:00
New Revision: 282cae0b9a602267ad7ef622f770066491332a11

URL: https://github.com/llvm/llvm-project/commit/282cae0b9a602267ad7ef622f770066491332a11
DIFF: https://github.com/llvm/llvm-project/commit/282cae0b9a602267ad7ef622f770066491332a11.diff

LOG: [Sema] Fix crash on __fp16 parameters in template instantiations

Fixes #61441.

Currently, Clang stores `nullptr` in the parameter lists inside
`FunctionProtoTypeLoc` if `__fp16` is used without pointer qualifiers.

Any code path that calls `Declarator::setInvalidType()` before
`GetFullTypeForDeclarator` will lead to the same problem downstream.

The relevant code is:
```cpp
if (D.isInvalidType())
  return Context.getTrivialTypeSourceInfo(T);

return GetTypeSourceInfoForDeclarator(state, T, TInfo);
```

`GetTypeSourceInfoForDeclarator` sets the parameter `Decl`, but we can't
call it when `isInvalidType() == true` as this causes other assertion
failures that seem harder to fix.

Reviewed By: kadircet

Differential Revision: https://reviews.llvm.org/D146426

Added: 
    clang/test/SemaCXX/GH61441.cpp

Modified: 
    clang/lib/Sema/SemaChecking.cpp
    clang/lib/Sema/SemaDeclCXX.cpp
    clang/lib/Sema/SemaLambda.cpp
    clang/lib/Sema/SemaTemplateInstantiate.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 02d1cb010db50..a3f2452b53d0c 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -15879,6 +15879,10 @@ bool Sema::CheckParmsForFunctionDef(ArrayRef<ParmVarDecl *> Parameters,
                                     bool CheckParameterNames) {
   bool HasInvalidParm = false;
   for (ParmVarDecl *Param : Parameters) {
+    if (!Param) {
+      HasInvalidParm = true;
+      continue;
+    }
     // C99 6.7.5.3p4: the parameters in a parameter type list in a
     // function declarator that is part of a function definition of
     // that function shall not have incomplete type.

diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 16e1071366b30..3dcc08f797811 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1712,6 +1712,8 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
 
 /// Check whether a function's parameter types are all literal types. If so,
 /// return true. If not, produce a suitable diagnostic and return false.
+/// If any ParamDecl is null, return false without producing a diagnostic.
+/// The code creating null parameters is responsible for producing a diagnostic.
 static bool CheckConstexprParameterTypes(Sema &SemaRef,
                                          const FunctionDecl *FD,
                                          Sema::CheckConstexprKind Kind) {
@@ -1721,6 +1723,8 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef,
                                               e = FT->param_type_end();
        i != e; ++i, ++ArgIndex) {
     const ParmVarDecl *PD = FD->getParamDecl(ArgIndex);
+    if (!PD)
+      return false;
     SourceLocation ParamLoc = PD->getLocation();
     if (CheckLiteralType(SemaRef, Kind, ParamLoc, *i,
                          diag::err_constexpr_non_literal_param, ArgIndex + 1,

diff  --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 6a79a03e02fda..3a82c7b3e8285 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -966,8 +966,11 @@ void Sema::CompleteLambdaCallOperator(
   if (!Params.empty()) {
     CheckParmsForFunctionDef(Params, /*CheckParameterNames=*/false);
     Method->setParams(Params);
-    for (auto P : Method->parameters())
+    for (auto P : Method->parameters()) {
+      if (!P)
+        continue;
       P->setOwningFunction(Method);
+    }
   }
 
   buildLambdaScopeReturnType(*this, LSI, Method, HasExplicitResultType);

diff  --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index da66ffea46f49..b4649ce4c413c 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1343,7 +1343,7 @@ namespace {
 
       CXXMethodDecl *MD = Result.getAs<LambdaExpr>()->getCallOperator();
       for (ParmVarDecl *PVD : MD->parameters()) {
-        if (!PVD->hasDefaultArg())
+        if (!PVD || !PVD->hasDefaultArg())
           continue;
         Expr *UninstExpr = PVD->getUninstantiatedDefaultArg();
         // FIXME: Obtain the source location for the '=' token.

diff  --git a/clang/test/SemaCXX/GH61441.cpp b/clang/test/SemaCXX/GH61441.cpp
new file mode 100644
index 0000000000000..73ff77515a7c4
--- /dev/null
+++ b/clang/test/SemaCXX/GH61441.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -cl-std=clc++ -fblocks %s
+// Checks Clang does not crash. We run in OpenCL mode to trigger block pointer
+// crash. The __fp16 crash happens in standard mode too.
+
+template <bool>
+int foo() {
+  auto x = [&](__fp16) { return 0; };       // expected-error {{not allowed}}
+  auto y = [&](void(^)(int)) { return 0; }; // expected-error {{not allowed}}
+  return 0;
+}
+
+int bar() { return foo<true>(); }


        


More information about the cfe-commits mailing list