Adding support for warning when a non-C compatible user-defined type is returned from an extern "C" function.

Fixes bug 6143

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150128 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Aaron Ballman 2012-02-09 01:21:34 +00:00
Родитель 7f99f43b36
Коммит 2c0bf24370
3 изменённых файлов: 52 добавлений и 1 удалений

Просмотреть файл

@ -163,7 +163,9 @@ def warn_parameter_size: Warning<
def warn_return_value_size: Warning<
"return value of %0 is a large (%1 bytes) pass-by-value object; "
"pass it by reference instead ?">, InGroup<LargeByValueCopy>;
def warn_return_value_udt: Warning<
"%0 has C-linkage specified, but returns user-defined type %1 which is "
"incompatible with C">, InGroup<ReturnType>;
def warn_implicit_function_decl : Warning<
"implicit declaration of function %0">,
InGroup<ImplicitFunctionDeclare>, DefaultIgnore;

Просмотреть файл

@ -5774,6 +5774,17 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
Context.BuiltinInfo.ForgetBuiltin(BuiltinID, Context.Idents);
}
}
// If this function is declared as being extern "C", then check to see if
// the function returns a UDT (class, struct, or union type) that is not C
// compatible, and if it does, warn the user.
if (NewFD->isExternC()) {
QualType R = NewFD->getResultType();
if (!R.isPODType(Context) &&
!R->isVoidType())
Diag( NewFD->getLocation(), diag::warn_return_value_udt )
<< NewFD << R;
}
}
return Redeclaration;
}

Просмотреть файл

@ -0,0 +1,38 @@
// RUN: %clang_cc1 -Wreturn-type -fsyntax-only -std=c++11 -verify %s
class A {
public:
A(const A&);
};
struct S {
int i;
double d;
virtual void B() {}
};
union U {
struct {
int i;
virtual void B() {} // Can only do this in C++11
} t;
};
struct S2 {
int i;
double d;
};
extern "C" U f3( void ); // expected-warning {{'f3' has C-linkage specified, but returns user-defined type 'U' which is incompatible with C}}
extern "C" S f0(void); // expected-warning {{'f0' has C-linkage specified, but returns user-defined type 'S' which is incompatible with C}}
extern "C" A f4( void ); // expected-warning {{'f4' has C-linkage specified, but returns user-defined type 'A' which is incompatible with C}}
// These should all be fine
extern "C" S2 f5( void );
extern "C" void f2( A x );
extern "C" void f6( S s );
extern "C" void f7( U u );
extern "C" double f8(void);
extern "C" long long f11( void );
extern "C" A *f10( void );