if (!getLangOptions().CPlusPlus) {
// Perform semantic checking on the function declaration.
bool isExplicitSpecialization=false;
- CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization,
- Redeclaration);
+ if (!NewFD->isInvalidDecl()) {
+ if (NewFD->getResultType()->isVariablyModifiedType()) {
+ // Functions returning a variably modified type violate C99 6.7.5.2p2
+ // because all functions have linkage.
+ Diag(NewFD->getLocation(), diag::err_vm_func_decl);
+ NewFD->setInvalidDecl();
+ } else {
+ if (NewFD->isMain())
+ CheckMain(NewFD, D.getDeclSpec());
+ CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization,
+ Redeclaration);
+ }
+ }
assert((NewFD->isInvalidDecl() || !Redeclaration ||
Previous.getResultKind() != LookupResult::FoundOverloaded) &&
"previous declaration set still overloaded");
}
// Perform semantic checking on the function declaration.
- if (!isDependentClassScopeExplicitSpecialization)
- CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization,
- Redeclaration);
+ if (!isDependentClassScopeExplicitSpecialization) {
+ if (NewFD->isInvalidDecl()) {
+ // If this is a class member, mark the class invalid immediately.
+ // This avoids some consistency errors later.
+ if (CXXMethodDecl* methodDecl = dyn_cast<CXXMethodDecl>(NewFD))
+ methodDecl->getParent()->setInvalidDecl();
+ } else {
+ if (NewFD->isMain())
+ CheckMain(NewFD, D.getDeclSpec());
+ CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization,
+ Redeclaration);
+ }
+ }
assert((NewFD->isInvalidDecl() || !Redeclaration ||
Previous.getResultKind() != LookupResult::FoundOverloaded) &&
LookupResult &Previous,
bool IsExplicitSpecialization,
bool &Redeclaration) {
- // If NewFD is already known erroneous, don't do any of this checking.
- if (NewFD->isInvalidDecl()) {
- // If this is a class member, mark the class invalid immediately.
- // This avoids some consistency errors later.
- if (isa<CXXMethodDecl>(NewFD))
- cast<CXXMethodDecl>(NewFD)->getParent()->setInvalidDecl();
-
- return;
- }
-
- if (NewFD->getResultType()->isVariablyModifiedType()) {
- // Functions returning a variably modified type violate C99 6.7.5.2p2
- // because all functions have linkage.
- Diag(NewFD->getLocation(), diag::err_vm_func_decl);
- return NewFD->setInvalidDecl();
- }
-
- if (NewFD->isMain())
- CheckMain(NewFD);
+ assert(!NewFD->getResultType()->isVariablyModifiedType()
+ && "Variably modified return types are not handled here");
// Check for a previous declaration of this name.
if (Previous.empty() && NewFD->isExternC()) {
}
}
-void Sema::CheckMain(FunctionDecl* FD) {
+void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
// C++ [basic.start.main]p3: A program that declares main to be inline
// or static is ill-formed.
// C99 6.7.4p4: In a hosted environment, the inline function specifier
// shall not appear in a declaration of main.
// static main is not an error under C99, but we should warn about it.
- bool isInline = FD->isInlineSpecified();
- bool isStatic = FD->getStorageClass() == SC_Static;
- if (isInline || isStatic) {
- unsigned diagID = diag::warn_unusual_main_decl;
- if (isInline || getLangOptions().CPlusPlus)
- diagID = diag::err_unusual_main_decl;
-
- int which = isStatic + (isInline << 1) - 1;
- Diag(FD->getLocation(), diagID) << which;
- }
+ if (FD->getStorageClass() == SC_Static)
+ Diag(DS.getStorageClassSpecLoc(), getLangOptions().CPlusPlus
+ ? diag::err_static_main : diag::warn_static_main)
+ << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
+ if (FD->isInlineSpecified())
+ Diag(DS.getInlineSpecLoc(), diag::err_inline_main)
+ << FixItHint::CreateRemoval(DS.getInlineSpecLoc());
QualType T = FD->getType();
assert(T->isFunctionType() && "function decl is not of function type");