From: Eli Friedman Date: Tue, 7 Apr 2009 19:37:57 +0000 (+0000) Subject: Diagnose uses of function specifiers on declarations which don't declare X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=85a5319ea4b5c916d7dd665e84af61e4a8a0b9c2;p=clang Diagnose uses of function specifiers on declarations which don't declare functions. Fixes PR3941. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68541 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index ddb066e3d6..4dbd12dd9f 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -87,6 +87,8 @@ def err_declarator_need_ident : Error<"declarator requires an identifier">; def err_bad_language : Error<"unknown linkage language">; def warn_use_out_of_scope_declaration : Warning< "use of out-of-scope declaration of %0">; +def err_inline_non_function : Error< + "'inline' can only appear on functions">; /// Built-in functions. def ext_implicit_lib_function_decl : ExtWarn< @@ -254,6 +256,8 @@ def err_mutable_nonmember : Error< "'mutable' can only be applied to member variables">; def err_virtual_non_function : Error< "'virtual' can only appear on non-static member functions">; +def err_explicit_non_function : Error< + "'virtual' can only appear on non-static member functions">; def err_virtual_out_of_class : Error< "'virtual' can only be specified inside the class definition">; def err_static_not_bitfield : Error<"static member %0 cannot be a bit-field">; diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 5582ac9f86..09ef84d4e2 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -338,6 +338,7 @@ public: DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition); void RegisterLocallyScopedExternCDecl(NamedDecl *ND, NamedDecl *PrevDecl, Scope *S); + void DiagnoseFunctionSpecifiers(Declarator& D); NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, Decl* PrevDecl, bool& InvalidDecl, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 7cf44bf6ac..54be9b4c3d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1478,6 +1478,24 @@ Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, NamedDecl *PrevDecl, } } +/// \brief Diagnose function specifiers on a declaration of an identifier that +/// does not identify a function. +void Sema::DiagnoseFunctionSpecifiers(Declarator& D) { + // FIXME: We should probably indicate the identifier in question to avoid + // confusion for constructs like "inline int a(), b;" + if (D.getDeclSpec().isInlineSpecified()) + Diag(D.getDeclSpec().getInlineSpecLoc(), + diag::err_inline_non_function); + + if (D.getDeclSpec().isVirtualSpecified()) + Diag(D.getDeclSpec().getVirtualSpecLoc(), + diag::err_virtual_non_function); + + if (D.getDeclSpec().isExplicitSpecified()) + Diag(D.getDeclSpec().getExplicitSpecLoc(), + diag::err_explicit_non_function); +} + NamedDecl* Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, Decl* PrevDecl, bool& InvalidDecl, @@ -1494,12 +1512,10 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (getLangOptions().CPlusPlus) { // Check that there are no default arguments (C++ only). CheckExtraCXXDefaultArguments(D); - - if (D.getDeclSpec().isVirtualSpecified()) - Diag(D.getDeclSpec().getVirtualSpecLoc(), - diag::err_virtual_non_function); } + DiagnoseFunctionSpecifiers(D); + TypedefDecl *NewTD = ParseTypedefDecl(S, D, R); if (!NewTD) return 0; @@ -1639,9 +1655,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, return 0; } - if (D.getDeclSpec().isVirtualSpecified()) - Diag(D.getDeclSpec().getVirtualSpecLoc(), - diag::err_virtual_non_function); + DiagnoseFunctionSpecifiers(D); bool ThreadSpecified = D.getDeclSpec().isThreadSpecified(); if (!DC->isRecord() && S->getFnParent() == 0) { @@ -2615,7 +2629,8 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { diag::err_invalid_storage_class_in_func_decl); D.getMutableDeclSpec().ClearStorageClassSpecs(); } - + DiagnoseFunctionSpecifiers(D); + // Check that there are no default arguments inside the type of this // parameter (C++ only). if (getLangOptions().CPlusPlus) @@ -3566,12 +3581,10 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, if (getLangOptions().CPlusPlus) { CheckExtraCXXDefaultArguments(D); - - if (D.getDeclSpec().isVirtualSpecified()) - Diag(D.getDeclSpec().getVirtualSpecLoc(), - diag::err_virtual_non_function); } + DiagnoseFunctionSpecifiers(D); + NamedDecl *PrevDecl = LookupName(S, II, LookupMemberName, true); if (PrevDecl && !isDeclInScope(PrevDecl, Record, S)) PrevDecl = 0; diff --git a/test/CodeGen/alias.c b/test/CodeGen/alias.c index c1a3baa929..b0c71fbdfc 100644 --- a/test/CodeGen/alias.c +++ b/test/CodeGen/alias.c @@ -20,7 +20,7 @@ int foo() __attribute__((alias("foo1"))); // RUN: grep '@bar1 = internal global i32 42' %t -static inline int bar1 = 42; +static int bar1 = 42; int bar() __attribute__((alias("bar1"))); diff --git a/test/Sema/inline.c b/test/Sema/inline.c new file mode 100644 index 0000000000..adcde51363 --- /dev/null +++ b/test/Sema/inline.c @@ -0,0 +1,6 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Check that we don't allow illegal uses of inline +inline int a; // expected-error{{'inline' can only appear on functions}} +typedef inline int b; // expected-error{{'inline' can only appear on functions}} +int d(inline int a); // expected-error{{'inline' can only appear on functions}} diff --git a/test/SemaCXX/inline.cpp b/test/SemaCXX/inline.cpp new file mode 100644 index 0000000000..7d0505a435 --- /dev/null +++ b/test/SemaCXX/inline.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Check that we don't allow illegal uses of inline +// (checking C++-only constructs here) +struct c {inline int a;}; // expected-error{{'inline' can only appear on functions}}