<div dir="ltr">Hi all,<br><div class="gmail_quote"><div dir="ltr"><div><br></div>This patch fixes PR15845 - Clang accepts invalid code, <a href="http://llvm.org/bugs/show_bug.cgi?id=15845" target="_blank">http://llvm.org/bugs/show_bug.cgi?id=15845</a>.<div>
Could someone please review this patch?</div>
<div>Thank you.<br></div><div>--Serge</div><div><br>Description:<br>The problem is that clang in C++ mode accepts the code:<br> int foo(xxx);<br>Clang intentionally accepts this code due to a check in Parser::ParseImplicitInt, which appeared in r156854.<br>
The comment in the inserted code states that MS supports implicit int in C++ mode, however it looks like none of VS2005, VS2008, VS2010 or VS2012 does it. So removing the check for MS extension solves the problem.</div><div>
Another problem - the same code compiled in C mode produces an error, while both GCC and MSC accept it. To fix it the message err_ident_list_in_fn_declaration was converted into warning.<br><br>Files:<br> include/clang/Basic/DiagnosticSemaKinds.td<br>
lib/Parse/ParseDecl.cpp<br> lib/Sema/SemaType.cpp<br> test/Sema/MicrosoftCompatibility.cpp<br> test/Sema/alloc_size.c<br> test/Sema/function.c<br> test/Sema/invalid-decl.c<br><br>-----------------------------------------------------------------------------------------------------<br>
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td<br>index 1461716..166dbab 100644<br>--- a/include/clang/Basic/DiagnosticSemaKinds.td<br>+++ b/include/clang/Basic/DiagnosticSemaKinds.td<br>
@@ -2314,8 +2314,9 @@ def err_void_only_param : Error<<br> "'void' must be the first and only parameter if specified">;<br> def err_void_param_qualified : Error<<br> "'void' as parameter must not have type qualifiers">;<br>
-def err_ident_list_in_fn_declaration : Error<<br>- "a parameter list without types is only allowed in a function definition">;<br>+def warn_ident_list_in_fn_declaration : Warning<<br>+ "a parameter list without types is only allowed in a function definition">,<br>
+ InGroup<C99Compat>;<br> def ext_param_not_declared : Extension<<br> "parameter %0 was not declared, defaulting to type 'int'">;<br> def err_param_typedef_of_void : Error<<br>diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp<br>
index d786ce2..2f0c1a3 100644<br>--- a/lib/Parse/ParseDecl.cpp<br>+++ b/lib/Parse/ParseDecl.cpp<br>@@ -2038,10 +2038,9 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,<br> // error, do lookahead to try to do better recovery. This never applies<br>
// within a type specifier. Outside of C++, we allow this even if the<br> // language doesn't "officially" support implicit int -- we support<br>- // implicit int as an extension in C99 and C11. Allegedly, MS also<br>
- // supports implicit int in C++ mode.<br>+ // implicit int as an extension in C99 and C11.<br> if (DSC != DSC_type_specifier && DSC != DSC_trailing &&<br>- (!getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt) &&<br>
+ !getLangOpts().CPlusPlus &&<br> isValidAfterIdentifierInDeclarator(NextToken())) {<br> // If this token is valid for implicit int, e.g. "static x = 4", then<br> // we just avoid eating the identifier, so it will be parsed as the<br>
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp<br>index 8bf5143..243b772 100644<br>--- a/lib/Sema/SemaType.cpp<br>+++ b/lib/Sema/SemaType.cpp<br>@@ -2742,7 +2742,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,<br>
if (FTI.NumArgs && FTI.ArgInfo[0].Param == 0) {<br> // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function<br> // definition.<br>- S.Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);<br>
+ S.Diag(FTI.ArgInfo[0].IdentLoc, diag::warn_ident_list_in_fn_declaration);<br> D.setInvalidType(true);<br> // Recover by creating a K&R-style function type.<br> T = Context.getFunctionNoProtoType(T);<br>
diff --git a/test/Sema/MicrosoftCompatibility.cpp b/test/Sema/MicrosoftCompatibility.cpp<br>new file mode 100644<br>index 0000000..15c2558<br>--- /dev/null<br>+++ b/test/Sema/MicrosoftCompatibility.cpp<br>@@ -0,0 +1,4 @@<br>
+// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify -fms-compatibility<br>+<br>+// PR15845<br>+int foo(xxx); // expected-error{{unknown type name}}<br>diff --git a/test/Sema/alloc_size.c b/test/Sema/alloc_size.c<br>
index 84f3932..0067bea 100644<br>--- a/test/Sema/alloc_size.c<br>+++ b/test/Sema/alloc_size.c<br>@@ -22,6 +22,6 @@ void *fn8(int, int) __attribute__((alloc_size(1, 1))); // OK<br> void* fn9(unsigned) __attribute__((alloc_size(12345678901234567890123))); // expected-warning {{integer constant is too large for its type}} // expected-error {{attribute parameter 1 is out of bounds}}<br>
<br> void* fn10(size_t, size_t) __attribute__((alloc_size(1,2))); // expected-error{{redefinition of parameter}} \<br>- // expected-error{{a parameter list without types is only allowed in a function definition}} \<br>
+ // expected-warning{{a parameter list without types is only allowed in a function definition}} \<br> // expected-error{{attribute parameter 1 is out of bounds}}<br>
void* fn11() __attribute__((alloc_size(1))); // expected-error{{attribute parameter 1 is out of bounds}}<br>diff --git a/test/Sema/function.c b/test/Sema/function.c<br>index bbf81a5..c0125ed 100644<br>--- a/test/Sema/function.c<br>
+++ b/test/Sema/function.c<br>@@ -17,7 +17,7 @@ void h(); // expected-note {{previous declaration is here}}<br> void h (const char *fmt, ...) {} // expected-error{{conflicting types for 'h'}}<br> <br> // PR1965<br>
-int t5(b); // expected-error {{parameter list without types}}<br>+int t5(b); // expected-warning {{parameter list without types}}<br> int t6(int x, g); // expected-warning {{type specifier missing, defaults to 'int'}}<br>
<br> int t7(, ); // expected-error {{expected parameter declarator}} expected-error {{expected parameter declarator}}<br>diff --git a/test/Sema/invalid-decl.c b/test/Sema/invalid-decl.c<br>index 950d51d..30b7657 100644<br>
--- a/test/Sema/invalid-decl.c<br>+++ b/test/Sema/invalid-decl.c<br>@@ -40,7 +40,7 @@ void foo() {<br> }<br> <br> void test2();<br>-void test2(undef); // expected-error {{a parameter list without types is only allowed in a function definition}}<br>
+void test2(undef); // expected-warning {{a parameter list without types is only allowed in a function definition}}<br> void test2() { }<br> <br> void test3();<br><br><br></div></div>
</div><br><br clear="all"><div><br></div>-- <br>Thanks,<br>--Serge<br>
</div>