]> granicus.if.org Git - clang/commitdiff
[Sema] Correctly recurse when looking for [*] in function definitions
authorDavid Majnemer <david.majnemer@gmail.com>
Tue, 7 Apr 2015 22:08:51 +0000 (22:08 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Tue, 7 Apr 2015 22:08:51 +0000 (22:08 +0000)
A [*] is only allowed in a declaration for a function, not in its
definition.  We didn't correctly recurse while looking for it, causing
us to crash in CodeGen instead of rejecting it.

This fixes PR23151.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@234363 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaChecking.cpp
test/Sema/vla.c

index 0501f63e90b2234b7dfa1b8e6c23eee7a6f95ff4..e557c50e027332220788e710d76f65276f82c7fe 100644 (file)
@@ -7705,6 +7705,31 @@ void Sema::CheckBitFieldInitialization(SourceLocation InitLoc,
   (void) AnalyzeBitFieldAssignment(*this, BitField, Init, InitLoc);
 }
 
+static void diagnoseArrayStarInParamType(Sema &S, QualType PType,
+                                         SourceLocation Loc) {
+  if (!PType->isVariablyModifiedType())
+    return;
+  if (const auto *PointerTy = dyn_cast<PointerType>(PType)) {
+    diagnoseArrayStarInParamType(S, PointerTy->getPointeeType(), Loc);
+    return;
+  }
+  if (const auto *ParenTy = dyn_cast<ParenType>(PType)) {
+    diagnoseArrayStarInParamType(S, ParenTy->getInnerType(), Loc);
+    return;
+  }
+
+  const ArrayType *AT = S.Context.getAsArrayType(PType);
+  if (!AT)
+    return;
+
+  if (AT->getSizeModifier() != ArrayType::Star) {
+    diagnoseArrayStarInParamType(S, AT->getElementType(), Loc);
+    return;
+  }
+
+  S.Diag(Loc, diag::err_array_star_in_function_definition);
+}
+
 /// CheckParmsForFunctionDef - Check that the parameters of the given
 /// function are appropriate for the definition of a function. This
 /// takes care of any checks that cannot be performed on the
@@ -7743,15 +7768,9 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P,
     //   notation in their sequences of declarator specifiers to specify
     //   variable length array types.
     QualType PType = Param->getOriginalType();
-    while (const ArrayType *AT = Context.getAsArrayType(PType)) {
-      if (AT->getSizeModifier() == ArrayType::Star) {
-        // FIXME: This diagnostic should point the '[*]' if source-location
-        // information is added for it.
-        Diag(Param->getLocation(), diag::err_array_star_in_function_definition);
-        break;
-      }
-      PType= AT->getElementType();
-    }
+    // FIXME: This diagnostic should point the '[*]' if source-location
+    // information is added for it.
+    diagnoseArrayStarInParamType(*this, PType, Param->getLocation());
 
     // MSVC destroys objects passed by value in the callee.  Therefore a
     // function definition which takes such a parameter must be able to call the
index e03dda8c5f6cdf6cef38b00f659665367ecfcd49..b9576bf8cfd61f8b2eececd013ac9653864a131f 100644 (file)
@@ -61,6 +61,9 @@ void pr5185(int a[*]) // expected-error {{variable length array must be bound in
 {
 }
 
+void pr23151(int (*p1)[*]) // expected-error {{variable length array must be bound in function definition}}
+{}
+
 // Make sure this isn't treated as an error
 int TransformBug(int a) {
  return sizeof(*(int(*)[({ goto v; v: a;})]) 0); // expected-warning {{use of GNU statement expression extension}}