forked from OSchip/llvm-project
Don't allow #include (and its friends #import, #include_next and
#__include_macros) in the arguments of a function-style macro. Directives in the arguments of such macros have undefined behaviour, and GCC does not correctly support these cases. In some situations, this can lead to better diagnostics. llvm-svn: 146765
This commit is contained in:
parent
b6c9d56eb5
commit
eb3ce7c3db
|
@ -202,8 +202,10 @@ def warn_cxx98_compat_variadic_macro : Warning<
|
|||
InGroup<CXX98CompatPedantic>, DefaultIgnore;
|
||||
def ext_named_variadic_macro : Extension<
|
||||
"named variadic macros are a GNU extension">, InGroup<VariadicMacros>;
|
||||
def err_embedded_include : Error<
|
||||
"embedding a #%0 directive within macro arguments is not supported">;
|
||||
def ext_embedded_directive : Extension<
|
||||
"embedding a directive within macro arguments is not portable">,
|
||||
"embedding a directive within macro arguments has undefined behavior">,
|
||||
InGroup<DiagGroup<"embedded-directive">>;
|
||||
def ext_missing_varargs_arg : Extension<
|
||||
"varargs argument missing, but tolerated as an extension">;
|
||||
|
|
|
@ -577,9 +577,25 @@ void Preprocessor::HandleDirective(Token &Result) {
|
|||
// A(abc
|
||||
// #warning blah
|
||||
// def)
|
||||
// If so, the user is relying on non-portable behavior, emit a diagnostic.
|
||||
if (InMacroArgs)
|
||||
// If so, the user is relying on undefined behavior, emit a diagnostic. Do
|
||||
// not support this for #include-like directives, since that can result in
|
||||
// terrible diagnostics, and does not work in GCC.
|
||||
if (InMacroArgs) {
|
||||
if (IdentifierInfo *II = Result.getIdentifierInfo()) {
|
||||
switch (II->getPPKeywordID()) {
|
||||
case tok::pp_include:
|
||||
case tok::pp_import:
|
||||
case tok::pp_include_next:
|
||||
case tok::pp___include_macros:
|
||||
Diag(Result, diag::err_embedded_include) << II->getName();
|
||||
DiscardUntilEndOfDirective();
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
Diag(Result, diag::ext_embedded_directive);
|
||||
}
|
||||
|
||||
TryAgain:
|
||||
switch (Result.getKind()) {
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
// RUN: %clang_cc1 %s -fsyntax-only -verify
|
||||
|
||||
// header1.h
|
||||
void fail(const char *);
|
||||
#define MUNCH(...) \
|
||||
({ int result = 0; __VA_ARGS__; if (!result) { fail(#__VA_ARGS__); }; result })
|
||||
|
||||
static inline int f(int k) {
|
||||
return MUNCH( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{returning 'void'}}
|
||||
if (k < 3)
|
||||
result = 24;
|
||||
else if (k > 4)
|
||||
result = k - 4;
|
||||
}
|
||||
|
||||
#include "macro_arg_directive.h" // expected-error {{embedding a #include directive within macro arguments is not supported}}
|
||||
|
||||
int g(int k) {
|
||||
return f(k) + f(k-1));
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// Support header for macro_arg_directive.c
|
||||
|
||||
int n;
|
||||
|
||||
struct S {
|
||||
int k;
|
||||
};
|
||||
|
||||
void g(int);
|
Loading…
Reference in New Issue