#include "clang/Sema/SemaInternal.h"
#include "TypeLocBuilder.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/CommentDiagnostic.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/HeaderSearch.h" // FIXME: Sema shouldn't depend on Lex
#include "clang/Lex/ModuleLoader.h" // FIXME: Sema shouldn't depend on Lex
#include "clang/Lex/Preprocessor.h" // FIXME: Sema shouldn't depend on Lex
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/CXXFieldCollector.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/Template.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Triple.h"
#include <algorithm>
#include <cstring>
#include <functional>
using namespace clang;
using namespace sema;
Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType) {
if (OwnedType) {
Decl *Group[2] = { OwnedType, Ptr };
return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, Group, 2));
}
return DeclGroupPtrTy::make(DeclGroupRef(Ptr));
}
namespace {
class TypeNameValidatorCCC : public CorrectionCandidateCallback {
public:
TypeNameValidatorCCC(bool AllowInvalid, bool WantClass=false)
: AllowInvalidDecl(AllowInvalid), WantClassName(WantClass) {
WantExpressionKeywords = false;
WantCXXNamedCasts = false;
WantRemainingKeywords = false;
}
virtual bool ValidateCandidate(const TypoCorrection &candidate) {
if (NamedDecl *ND = candidate.getCorrectionDecl())
return (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
(AllowInvalidDecl || !ND->isInvalidDecl());
else
return !WantClassName && candidate.isKeyword();
}
private:
bool AllowInvalidDecl;
bool WantClassName;
};
}
bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
switch (Kind) {
case tok::kw_short:
case tok::kw_long:
case tok::kw___int64:
case tok::kw___int128:
case tok::kw_signed:
case tok::kw_unsigned:
case tok::kw_void:
case tok::kw_char:
case tok::kw_int:
case tok::kw_half:
case tok::kw_float:
case tok::kw_double:
case tok::kw_wchar_t:
case tok::kw_bool:
case tok::kw___underlying_type:
return true;
case tok::annot_typename:
case tok::kw_char16_t:
case tok::kw_char32_t:
case tok::kw_typeof:
case tok::annot_decltype:
case tok::kw_decltype:
return getLangOpts().CPlusPlus;
default:
break;
}
return false;
}
ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
Scope *S, CXXScopeSpec *SS,
bool isClassName, bool HasTrailingDot,
ParsedType ObjectTypePtr,
bool IsCtorOrDtorName,
bool WantNontrivialTypeSourceInfo,
IdentifierInfo **CorrectedII) {
DeclContext *LookupCtx = 0;
if (ObjectTypePtr) {
QualType ObjectType = ObjectTypePtr.get();
if (ObjectType->isRecordType())
LookupCtx = computeDeclContext(ObjectType);
} else if (SS && SS->isNotEmpty()) {
LookupCtx = computeDeclContext(*SS, false);
if (!LookupCtx) {
if (isDependentScopeSpecifier(*SS)) {
if (!isClassName && !IsCtorOrDtorName)
return ParsedType();
if (WantNontrivialTypeSourceInfo)
return ActOnTypenameType(S, SourceLocation(), *SS, II, NameLoc).get();
NestedNameSpecifierLoc QualifierLoc = SS->getWithLocInContext(Context);
QualType T =
CheckTypenameType(ETK_None, SourceLocation(), QualifierLoc,
II, NameLoc);
return ParsedType::make(T);
}
return ParsedType();
}
if (!LookupCtx->isDependentContext() &&
RequireCompleteDeclContext(*SS, LookupCtx))
return ParsedType();
}
LookupNameKind Kind = isClassName ? LookupNestedNameSpecifierName :
LookupOrdinaryName;
LookupResult Result(*this, &II, NameLoc, Kind);
if (LookupCtx) {
LookupQualifiedName(Result, LookupCtx);
if (ObjectTypePtr && Result.empty()) {
LookupName(Result, S);
}
} else {
LookupName(Result, S);
}
NamedDecl *IIDecl = 0;
switch (Result.getResultKind()) {
case LookupResult::NotFound:
case LookupResult::NotFoundInCurrentInstantiation:
if (CorrectedII) {
TypeNameValidatorCCC Validator(true, isClassName);
TypoCorrection Correction = CorrectTypo(Result.getLookupNameInfo(),
Kind, S, SS, Validator);
IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo();
TemplateTy Template;
bool MemberOfUnknownSpecialization;
UnqualifiedId TemplateName;
TemplateName.setIdentifier(NewII, NameLoc);
NestedNameSpecifier *NNS = Correction.getCorrectionSpecifier();
CXXScopeSpec NewSS, *NewSSPtr = SS;
if (SS && NNS) {
NewSS.MakeTrivial(Context, NNS, SourceRange(NameLoc));
NewSSPtr = &NewSS;
}
if (Correction && (NNS || NewII != &II) &&
!(getLangOpts().CPlusPlus && NewSSPtr &&
isTemplateName(S, *NewSSPtr, false, TemplateName, ParsedType(),
false, Template, MemberOfUnknownSpecialization))) {
ParsedType Ty = getTypeName(*NewII, NameLoc, S, NewSSPtr,
isClassName, HasTrailingDot, ObjectTypePtr,
IsCtorOrDtorName,
WantNontrivialTypeSourceInfo);
if (Ty) {
diagnoseTypo(Correction,
PDiag(diag::err_unknown_type_or_class_name_suggest)
<< Result.getLookupName() << isClassName);
if (SS && NNS)
SS->MakeTrivial(Context, NNS, SourceRange(NameLoc));
*CorrectedII = NewII;
return Ty;
}
}
}
case LookupResult::FoundOverloaded:
case LookupResult::FoundUnresolvedValue:
Result.suppressDiagnostics();
return ParsedType();
case LookupResult::Ambiguous:
if (Result.getAmbiguityKind() == LookupResult::AmbiguousTagHiding) {
Result.suppressDiagnostics();
return ParsedType();
}
for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end();
Res != ResEnd; ++Res) {
if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res)) {
if (!IIDecl ||
(*Res)->getLocation().getRawEncoding() <
IIDecl->getLocation().getRawEncoding())
IIDecl = *Res;
}
}
if (!IIDecl) {
Result.suppressDiagnostics();
return ParsedType();
}
break;
case LookupResult::Found:
IIDecl = Result.getFoundDecl();
break;
}
assert(IIDecl && "Didn't find decl");
QualType T;
if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) {
DiagnoseUseOfDecl(IIDecl, NameLoc);
if (T.isNull())
T = Context.getTypeDeclType(TD);
if (SS && SS->isNotEmpty() && !IsCtorOrDtorName) {
if (WantNontrivialTypeSourceInfo) {
TypeLocBuilder Builder;
Builder.pushTypeSpec(T).setNameLoc(NameLoc);
T = getElaboratedType(ETK_None, *SS, T);
ElaboratedTypeLoc ElabTL = Builder.push<ElaboratedTypeLoc>(T);
ElabTL.setElaboratedKeywordLoc(SourceLocation());
ElabTL.setQualifierLoc(SS->getWithLocInContext(Context));
return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
} else {
T = getElaboratedType(ETK_None, *SS, T);
}
}
} else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
(void)DiagnoseUseOfDecl(IDecl, NameLoc);
if (!HasTrailingDot)
T = Context.getObjCInterfaceType(IDecl);
}
if (T.isNull()) {
Result.suppressDiagnostics();
return ParsedType();
}
return ParsedType::make(T);
}
DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
LookupResult R(*this, &II, SourceLocation(), LookupTagName);
LookupName(R, S, false);
R.suppressDiagnostics();
if (R.getResultKind() == LookupResult::Found)
if (const TagDecl *TD = R.getAsSingle<TagDecl>()) {
switch (TD->getTagKind()) {
case TTK_Struct: return DeclSpec::TST_struct;
case TTK_Interface: return DeclSpec::TST_interface;
case TTK_Union: return DeclSpec::TST_union;
case TTK_Class: return DeclSpec::TST_class;
case TTK_Enum: return DeclSpec::TST_enum;
}
}
return DeclSpec::TST_unspecified;
}
bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S) {
if (CurContext->isRecord()) {
const Type *Ty = SS->getScopeRep()->getAsType();
CXXRecordDecl *RD = cast<CXXRecordDecl>(CurContext);
for (CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(),
BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base)
if (Context.hasSameUnqualifiedType(QualType(Ty, 1), Base->getType()))
return true;
return S->isFunctionPrototypeScope();
}
return CurContext->isFunctionOrMethod() || S->isFunctionPrototypeScope();
}
bool Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
SourceLocation IILoc,
Scope *S,
CXXScopeSpec *SS,
ParsedType &SuggestedType) {
SuggestedType = ParsedType();
TypeNameValidatorCCC Validator(false);
if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(II, IILoc),
LookupOrdinaryName, S, SS,
Validator)) {
if (Corrected.isKeyword()) {
diagnoseTypo(Corrected, PDiag(diag::err_unknown_typename_suggest) << II);
II = Corrected.getCorrectionAsIdentifierInfo();
} else {
if (!SS || !SS->isSet()) {
diagnoseTypo(Corrected,
PDiag(diag::err_unknown_typename_suggest) << II);
} else if (DeclContext *DC = computeDeclContext(*SS, false)) {
std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&
II->getName().equals(CorrectedStr);
diagnoseTypo(Corrected,
PDiag(diag::err_unknown_nested_typename_suggest)
<< II << DC << DroppedSpecifier << SS->getRange());
} else {
llvm_unreachable("could not have corrected a typo here");
}
CXXScopeSpec tmpSS;
if (Corrected.getCorrectionSpecifier())
tmpSS.MakeTrivial(Context, Corrected.getCorrectionSpecifier(),
SourceRange(IILoc));
SuggestedType = getTypeName(*Corrected.getCorrectionAsIdentifierInfo(),
IILoc, S, tmpSS.isSet() ? &tmpSS : SS, false,
false, ParsedType(),
false,
true);
}
return true;
}
if (getLangOpts().CPlusPlus) {
UnqualifiedId Name;
Name.setIdentifier(II, IILoc);
CXXScopeSpec EmptySS;
TemplateTy TemplateResult;
bool MemberOfUnknownSpecialization;
if (isTemplateName(S, SS ? *SS : EmptySS, false,
Name, ParsedType(), true, TemplateResult,
MemberOfUnknownSpecialization) == TNK_Type_template) {
TemplateName TplName = TemplateResult.get();
Diag(IILoc, diag::err_template_missing_args) << TplName;
if (TemplateDecl *TplDecl = TplName.getAsTemplateDecl()) {
Diag(TplDecl->getLocation(), diag::note_template_decl_here)
<< TplDecl->getTemplateParameters()->getSourceRange();
}
return true;
}
}
if (!SS || (!SS->isSet() && !SS->isInvalid()))
Diag(IILoc, diag::err_unknown_typename) << II;
else if (DeclContext *DC = computeDeclContext(*SS, false))
Diag(IILoc, diag::err_typename_nested_not_found)
<< II << DC << SS->getRange();
else if (isDependentScopeSpecifier(*SS)) {
unsigned DiagID = diag::err_typename_missing;
if (getLangOpts().MSVCCompat && isMicrosoftMissingTypename(SS, S))
DiagID = diag::warn_typename_missing;
Diag(SS->getRange().getBegin(), DiagID)
<< SS->getScopeRep() << II->getName()
<< SourceRange(SS->getRange().getBegin(), IILoc)
<< FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename ");
SuggestedType = ActOnTypenameType(S, SourceLocation(),
*SS, *II, IILoc).get();
} else {
assert(SS && SS->isInvalid() &&
"Invalid scope specifier has already been diagnosed");
}
return true;
}
static bool isResultTypeOrTemplate(LookupResult &R, const Token &NextToken) {
bool CheckTemplate = R.getSema().getLangOpts().CPlusPlus &&
NextToken.is(tok::less);
for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) {
if (isa<TypeDecl>(*I) || isa<ObjCInterfaceDecl>(*I))
return true;
if (CheckTemplate && isa<TemplateDecl>(*I))
return true;
}
return false;
}
static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result,
Scope *S, CXXScopeSpec &SS,
IdentifierInfo *&Name,
SourceLocation NameLoc) {
LookupResult R(SemaRef, Name, NameLoc, Sema::LookupTagName);
SemaRef.LookupParsedName(R, S, &SS);
if (TagDecl *Tag = R.getAsSingle<TagDecl>()) {
const char *TagName = 0;
const char *FixItTagName = 0;
switch (Tag->getTagKind()) {
case TTK_Class:
TagName = "class";
FixItTagName = "class ";
break;
case TTK_Enum:
TagName = "enum";
FixItTagName = "enum ";
break;
case TTK_Struct:
TagName = "struct";
FixItTagName = "struct ";
break;
case TTK_Interface:
TagName = "__interface";
FixItTagName = "__interface ";
break;
case TTK_Union:
TagName = "union";
FixItTagName = "union ";
break;
}
SemaRef.Diag(NameLoc, diag::err_use_of_tag_name_without_tag)
<< Name << TagName << SemaRef.getLangOpts().CPlusPlus
<< FixItHint::CreateInsertion(NameLoc, FixItTagName);
for (LookupResult::iterator I = Result.begin(), IEnd = Result.end();
I != IEnd; ++I)
SemaRef.Diag((*I)->getLocation(), diag::note_decl_hiding_tag_type)
<< Name << TagName;
Result.clear(Sema::LookupTagName);
SemaRef.LookupParsedName(Result, S, &SS);
return true;
}
return false;
}
static ParsedType buildNestedType(Sema &S, CXXScopeSpec &SS,
QualType T, SourceLocation NameLoc) {
ASTContext &Context = S.Context;
TypeLocBuilder Builder;
Builder.pushTypeSpec(T).setNameLoc(NameLoc);
T = S.getElaboratedType(ETK_None, SS, T);
ElaboratedTypeLoc ElabTL = Builder.push<ElaboratedTypeLoc>(T);
ElabTL.setElaboratedKeywordLoc(SourceLocation());
ElabTL.setQualifierLoc(SS.getWithLocInContext(Context));
return S.CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
}
Sema::NameClassification Sema::ClassifyName(Scope *S,
CXXScopeSpec &SS,
IdentifierInfo *&Name,
SourceLocation NameLoc,
const Token &NextToken,
bool IsAddressOfOperand,
CorrectionCandidateCallback *CCC) {
DeclarationNameInfo NameInfo(Name, NameLoc);
ObjCMethodDecl *CurMethod = getCurMethodDecl();
if (NextToken.is(tok::coloncolon)) {
BuildCXXNestedNameSpecifier(S, *Name, NameLoc, NextToken.getLocation(),
QualType(), false, SS, 0, false);
}
LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName);
LookupParsedName(Result, S, &SS, !CurMethod);
if (!SS.isSet() && CurMethod && !isResultTypeOrTemplate(Result, NextToken)) {
ExprResult E = LookupInObjCMethod(Result, S, Name, true);
if (E.get() || E.isInvalid())
return E;
}
bool SecondTry = false;
bool IsFilteredTemplateName = false;
Corrected:
switch (Result.getResultKind()) {
case LookupResult::NotFound:
if (!SS.isSet() && NextToken.is(tok::l_paren)) {
if (getLangOpts().CPlusPlus)
return BuildDeclarationNameExpr(SS, Result, true);
if (NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *Name, S)) {
Result.addDecl(D);
Result.resolveKind();
return BuildDeclarationNameExpr(SS, Result, false);
}
}
if (!getLangOpts().CPlusPlus && !SecondTry &&
isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) {
break;
}
if (!SecondTry && CCC) {
SecondTry = true;
if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),
Result.getLookupKind(), S,
&SS, *CCC)) {
unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest;
unsigned QualifiedDiag = diag::err_no_member_suggest;
NamedDecl *FirstDecl = Corrected.getCorrectionDecl();
NamedDecl *UnderlyingFirstDecl
= FirstDecl? FirstDecl->getUnderlyingDecl() : 0;
if (getLangOpts().CPlusPlus && NextToken.is(tok::less) &&
UnderlyingFirstDecl && isa<TemplateDecl>(UnderlyingFirstDecl)) {
UnqualifiedDiag = diag::err_no_template_suggest;
QualifiedDiag = diag::err_no_member_template_suggest;
} else if (UnderlyingFirstDecl &&
(isa<TypeDecl>(UnderlyingFirstDecl) ||
isa<ObjCInterfaceDecl>(UnderlyingFirstDecl) ||
isa<ObjCCompatibleAliasDecl>(UnderlyingFirstDecl))) {
UnqualifiedDiag = diag::err_unknown_typename_suggest;
QualifiedDiag = diag::err_unknown_nested_typename_suggest;
}
if (SS.isEmpty()) {
diagnoseTypo(Corrected, PDiag(UnqualifiedDiag) << Name);
} else { std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&
Name->getName().equals(CorrectedStr);
diagnoseTypo(Corrected, PDiag(QualifiedDiag)
<< Name << computeDeclContext(SS, false)
<< DroppedSpecifier << SS.getRange());
}
Name = Corrected.getCorrectionAsIdentifierInfo();
if (Corrected.isKeyword())
return Name;
Result.clear();
Result.setLookupName(Corrected.getCorrection());
if (FirstDecl)
Result.addDecl(FirstDecl);
if (ObjCIvarDecl *Ivar = Result.getAsSingle<ObjCIvarDecl>()) {
Result.clear();
ExprResult E(LookupInObjCMethod(Result, S, Ivar->getIdentifier()));
return E;
}
goto Corrected;
}
}
Result.suppressDiagnostics();
return NameClassification::Unknown();
case LookupResult::NotFoundInCurrentInstantiation: {
return ActOnDependentIdExpression(SS, SourceLocation(),
NameInfo, IsAddressOfOperand,
0);
}
case LookupResult::Found:
case LookupResult::FoundOverloaded:
case LookupResult::FoundUnresolvedValue:
break;
case LookupResult::Ambiguous:
if (getLangOpts().CPlusPlus && NextToken.is(tok::less) &&
hasAnyAcceptableTemplateNames(Result)) {
FilterAcceptableTemplateNames(Result);
if (!Result.isAmbiguous()) {
IsFilteredTemplateName = true;
break;
}
}
return NameClassification::Error();
}
if (getLangOpts().CPlusPlus && NextToken.is(tok::less) &&
(IsFilteredTemplateName || hasAnyAcceptableTemplateNames(Result))) {
if (!IsFilteredTemplateName)
FilterAcceptableTemplateNames(Result);
if (!Result.empty()) {
bool IsFunctionTemplate;
bool IsVarTemplate;
TemplateName Template;
if (Result.end() - Result.begin() > 1) {
IsFunctionTemplate = true;
Template = Context.getOverloadedTemplateName(Result.begin(),
Result.end());
} else {
TemplateDecl *TD
= cast<TemplateDecl>((*Result.begin())->getUnderlyingDecl());
IsFunctionTemplate = isa<FunctionTemplateDecl>(TD);
IsVarTemplate = isa<VarTemplateDecl>(TD);
if (SS.isSet() && !SS.isInvalid())
Template = Context.getQualifiedTemplateName(SS.getScopeRep(),
false,
TD);
else
Template = TemplateName(TD);
}
if (IsFunctionTemplate) {
Result.suppressDiagnostics();
return NameClassification::FunctionTemplate(Template);
}
return IsVarTemplate ? NameClassification::VarTemplate(Template)
: NameClassification::TypeTemplate(Template);
}
}
NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl();
if (TypeDecl *Type = dyn_cast<TypeDecl>(FirstDecl)) {
DiagnoseUseOfDecl(Type, NameLoc);
QualType T = Context.getTypeDeclType(Type);
if (SS.isNotEmpty())
return buildNestedType(*this, SS, T, NameLoc);
return ParsedType::make(T);
}
ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(FirstDecl);
if (!Class) {
if (ObjCCompatibleAliasDecl *Alias
= dyn_cast<ObjCCompatibleAliasDecl>(FirstDecl))
Class = Alias->getClassInterface();
}
if (Class) {
DiagnoseUseOfDecl(Class, NameLoc);
if (NextToken.is(tok::period)) {
Result.suppressDiagnostics();
return NameClassification::Unknown();
}
QualType T = Context.getObjCInterfaceType(Class);
return ParsedType::make(T);
}
if (isa<TemplateDecl>(FirstDecl) && !isa<FunctionTemplateDecl>(FirstDecl))
return NameClassification::TypeTemplate(
TemplateName(cast<TemplateDecl>(FirstDecl)));
bool NextIsOp = NextToken.is(tok::amp) || NextToken.is(tok::star);
if ((NextToken.is(tok::identifier) ||
(NextIsOp &&
FirstDecl->getUnderlyingDecl()->isFunctionOrFunctionTemplate())) &&
isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) {
TypeDecl *Type = Result.getAsSingle<TypeDecl>();
DiagnoseUseOfDecl(Type, NameLoc);
QualType T = Context.getTypeDeclType(Type);
if (SS.isNotEmpty())
return buildNestedType(*this, SS, T, NameLoc);
return ParsedType::make(T);
}
if (FirstDecl->isCXXClassMember())
return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result, 0);
bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren));
return BuildDeclarationNameExpr(SS, Result, ADL);
}
DeclContext *Sema::getContainingDC(DeclContext *DC) {
if (isa<FunctionDecl>(DC) && !isLambdaCallOperator(DC)) {
DC = DC->getLexicalParent();
if (!isa<CXXRecordDecl>(DC))
return DC;
while (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC->getLexicalParent()))
DC = RD;
return DC;
}
return DC->getLexicalParent();
}
void Sema::PushDeclContext(Scope *S, DeclContext *DC) {
assert(getContainingDC(DC) == CurContext &&
"The next DeclContext should be lexically contained in the current one.");
CurContext = DC;
S->setEntity(DC);
}
void Sema::PopDeclContext() {
assert(CurContext && "DeclContext imbalance!");
CurContext = getContainingDC(CurContext);
assert(CurContext && "Popped translation unit!");
}
void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) {
assert(!S->getEntity() && "scope already has entity");
#ifndef NDEBUG
Scope *Ancestor = S->getParent();
while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
assert(Ancestor->getEntity() == CurContext && "ancestor context mismatch");
#endif
CurContext = DC;
S->setEntity(DC);
}
void Sema::ExitDeclaratorContext(Scope *S) {
assert(S->getEntity() == CurContext && "Context imbalance!");
Scope *Ancestor = S->getParent();
while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
CurContext = Ancestor->getEntity();
}
void Sema::ActOnReenterFunctionContext(Scope* S, Decl *D) {
FunctionDecl *FD = D->getAsFunction();
if (!FD)
return;
assert(CurContext == FD->getLexicalParent() &&
"The next DeclContext should be lexically contained in the current one.");
CurContext = FD;
S->setEntity(CurContext);
for (unsigned P = 0, NumParams = FD->getNumParams(); P < NumParams; ++P) {
ParmVarDecl *Param = FD->getParamDecl(P);
if (Param->getIdentifier()) {
S->AddDecl(Param);
IdResolver.AddDecl(Param);
}
}
}
void Sema::ActOnExitFunctionContext() {
assert(CurContext && "DeclContext imbalance!");
CurContext = CurContext->getLexicalParent();
assert(CurContext && "Popped translation unit!");
}
static bool AllowOverloadingOfFunction(LookupResult &Previous,
ASTContext &Context) {
if (Context.getLangOpts().CPlusPlus)
return true;
if (Previous.getResultKind() == LookupResult::FoundOverloaded)
return true;
return (Previous.getResultKind() == LookupResult::Found
&& Previous.getFoundDecl()->hasAttr<OverloadableAttr>());
}
void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
while (S->getEntity() && S->getEntity()->isTransparentContext())
S = S->getParent();
if (AddToContext)
CurContext->addDecl(D);
if (getLangOpts().CPlusPlus && D->isOutOfLine() &&
!D->getDeclContext()->getRedeclContext()->Equals(
D->getLexicalDeclContext()->getRedeclContext()) &&
!D->getLexicalDeclContext()->isFunctionOrMethod())
return;
if (isa<FunctionDecl>(D) &&
cast<FunctionDecl>(D)->isFunctionTemplateSpecialization())
return;
IdentifierResolver::iterator I = IdResolver.begin(D->getDeclName()),
IEnd = IdResolver.end();
for (; I != IEnd; ++I) {
if (S->isDeclScope(*I) && D->declarationReplaces(*I)) {
S->RemoveDecl(*I);
IdResolver.RemoveDecl(*I);
break;
}
}
S->AddDecl(D);
if (isa<LabelDecl>(D) && !cast<LabelDecl>(D)->isGnuLocal()) {
for (I = IdResolver.begin(D->getDeclName()); I != IEnd; ++I) {
DeclContext *IDC = (*I)->getLexicalDeclContext()->getRedeclContext();
if (IDC == CurContext) {
if (!S->isDeclScope(*I))
continue;
} else if (IDC->Encloses(CurContext))
break;
}
IdResolver.InsertDeclAfter(I, D);
} else {
IdResolver.AddDecl(D);
}
}
void Sema::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) {
if (IdResolver.tryAddTopLevelDecl(D, Name) && TUScope)
TUScope->AddDecl(D);
}
bool Sema::isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S,
bool AllowInlineNamespace) {
return IdResolver.isDeclInScope(D, Ctx, S, AllowInlineNamespace);
}
Scope *Sema::getScopeForDeclContext(Scope *S, DeclContext *DC) {
DeclContext *TargetDC = DC->getPrimaryContext();
do {
if (DeclContext *ScopeDC = S->getEntity())
if (ScopeDC->getPrimaryContext() == TargetDC)
return S;
} while ((S = S->getParent()));
return 0;
}
static bool isOutOfScopePreviousDeclaration(NamedDecl *,
DeclContext*,
ASTContext&);
void Sema::FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S,
bool ConsiderLinkage,
bool AllowInlineNamespace) {
LookupResult::Filter F = R.makeFilter();
while (F.hasNext()) {
NamedDecl *D = F.next();
if (isDeclInScope(D, Ctx, S, AllowInlineNamespace))
continue;
if (ConsiderLinkage && isOutOfScopePreviousDeclaration(D, Ctx, Context))
continue;
F.erase();
}
F.done();
}
static bool isUsingDecl(NamedDecl *D) {
return isa<UsingShadowDecl>(D) ||
isa<UnresolvedUsingTypenameDecl>(D) ||
isa<UnresolvedUsingValueDecl>(D);
}
static void RemoveUsingDecls(LookupResult &R) {
LookupResult::Filter F = R.makeFilter();
while (F.hasNext())
if (isUsingDecl(F.next()))
F.erase();
F.done();
}
static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) {
if (D->doesThisDeclarationHaveABody())
return false;
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D))
return CD->isCopyConstructor();
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
return Method->isCopyAssignmentOperator();
return false;
}
bool Sema::mightHaveNonExternalLinkage(const DeclaratorDecl *D) {
const DeclContext *DC = D->getDeclContext();
while (!DC->isTranslationUnit()) {
if (const RecordDecl *RD = dyn_cast<RecordDecl>(DC)){
if (!RD->hasNameForLinkage())
return true;
}
DC = DC->getParent();
}
return !D->isExternallyVisible();
}
static bool isMainFileLoc(const Sema &S, SourceLocation Loc) {
if (S.TUKind != TU_Complete)
return false;
return S.SourceMgr.isInMainFile(Loc);
}
bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
assert(D);
if (D->isInvalidDecl() || D->isUsed() || D->hasAttr<UnusedAttr>())
return false;
if (D->getDeclContext()->isDependentContext() ||
D->getLexicalDeclContext()->isDependentContext())
return false;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
return false;
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
if (MD->isVirtual() || IsDisallowedCopyOrAssign(MD))
return false;
} else {
if (FD->isInlineSpecified() &&
!isMainFileLoc(*this, FD->getLocation()))
return false;
}
if (FD->doesThisDeclarationHaveABody() &&
Context.DeclMustBeEmitted(FD))
return false;
} else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (!isMainFileLoc(*this, VD->getLocation()))
return false;
if (Context.DeclMustBeEmitted(VD))
return false;
if (VD->isStaticDataMember() &&
VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
return false;
} else {
return false;
}
return mightHaveNonExternalLinkage(D);
}
void Sema::MarkUnusedFileScopedDecl(const DeclaratorDecl *D) {
if (!D)
return;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
const FunctionDecl *First = FD->getFirstDecl();
if (FD != First && ShouldWarnIfUnusedFileScopedDecl(First))
return; }
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
const VarDecl *First = VD->getFirstDecl();
if (VD != First && ShouldWarnIfUnusedFileScopedDecl(First))
return; }
if (ShouldWarnIfUnusedFileScopedDecl(D))
UnusedFileScopedDecls.push_back(D);
}
static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
if (D->isInvalidDecl())
return false;
if (D->isReferenced() || D->isUsed() || D->hasAttr<UnusedAttr>() ||
D->hasAttr<ObjCPreciseLifetimeAttr>())
return false;
if (isa<LabelDecl>(D))
return true;
if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) ||
!D->getDeclContext()->isFunctionOrMethod())
return false;
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
QualType Ty = VD->getType();
if (const TypedefType *TT = Ty->getAs<TypedefType>()) {
if (TT->getDecl()->hasAttr<UnusedAttr>())
return false;
}
if (Ty->isIncompleteType() || Ty->isDependentType())
return false;
if (const TagType *TT = Ty->getAs<TagType>()) {
const TagDecl *Tag = TT->getDecl();
if (Tag->hasAttr<UnusedAttr>())
return false;
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Tag)) {
if (!RD->hasTrivialDestructor() && !RD->hasAttr<WarnUnusedAttr>())
return false;
if (const Expr *Init = VD->getInit()) {
if (const ExprWithCleanups *Cleanups = dyn_cast<ExprWithCleanups>(Init))
Init = Cleanups->getSubExpr();
const CXXConstructExpr *Construct =
dyn_cast<CXXConstructExpr>(Init);
if (Construct && !Construct->isElidable()) {
CXXConstructorDecl *CD = Construct->getConstructor();
if (!CD->isTrivial() && !RD->hasAttr<WarnUnusedAttr>())
return false;
}
}
}
}
}
return true;
}
static void GenerateFixForUnusedDecl(const NamedDecl *D, ASTContext &Ctx,
FixItHint &Hint) {
if (isa<LabelDecl>(D)) {
SourceLocation AfterColon = Lexer::findLocationAfterToken(D->getLocEnd(),
tok::colon, Ctx.getSourceManager(), Ctx.getLangOpts(), true);
if (AfterColon.isInvalid())
return;
Hint = FixItHint::CreateRemoval(CharSourceRange::
getCharRange(D->getLocStart(), AfterColon));
}
return;
}
void Sema::DiagnoseUnusedDecl(const NamedDecl *D) {
FixItHint Hint;
if (!ShouldDiagnoseUnusedDecl(D))
return;
GenerateFixForUnusedDecl(D, Context, Hint);
unsigned DiagID;
if (isa<VarDecl>(D) && cast<VarDecl>(D)->isExceptionVariable())
DiagID = diag::warn_unused_exception_param;
else if (isa<LabelDecl>(D))
DiagID = diag::warn_unused_label;
else
DiagID = diag::warn_unused_variable;
Diag(D->getLocation(), DiagID) << D->getDeclName() << Hint;
}
static void CheckPoppedLabel(LabelDecl *L, Sema &S) {
if (L->getStmt() == 0)
S.Diag(L->getLocation(), diag::err_undeclared_label_use) <<L->getDeclName();
}
void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
if (S->decl_empty()) return;
assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) &&
"Scope shouldn't contain decls!");
for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
I != E; ++I) {
Decl *TmpD = (*I);
assert(TmpD && "This decl didn't get pushed??");
assert(isa<NamedDecl>(TmpD) && "Decl isn't NamedDecl?");
NamedDecl *D = cast<NamedDecl>(TmpD);
if (!D->getDeclName()) continue;
if (!S->hasUnrecoverableErrorOccurred())
DiagnoseUnusedDecl(D);
if (LabelDecl *LD = dyn_cast<LabelDecl>(D))
CheckPoppedLabel(LD, *this);
IdResolver.RemoveDecl(D);
}
}
void Sema::ActOnStartFunctionDeclarator() {
++InFunctionDeclarator;
}
void Sema::ActOnEndFunctionDeclarator() {
assert(InFunctionDeclarator);
--InFunctionDeclarator;
}
ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id,
SourceLocation IdLoc,
bool DoTypoCorrection) {
NamedDecl *IDecl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName);
if (!IDecl && DoTypoCorrection) {
DeclFilterCCC<ObjCInterfaceDecl> Validator;
if (TypoCorrection C = CorrectTypo(DeclarationNameInfo(Id, IdLoc),
LookupOrdinaryName, TUScope, NULL,
Validator)) {
diagnoseTypo(C, PDiag(diag::err_undef_interface_suggest) << Id);
IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>();
Id = IDecl->getIdentifier();
}
}
ObjCInterfaceDecl *Def = dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);
if (Def && Def->getDefinition())
Def = Def->getDefinition();
return Def;
}
Scope *Sema::getNonFieldDeclScope(Scope *S) {
while (((S->getFlags() & Scope::DeclScope) == 0) ||
(S->getEntity() && S->getEntity()->isTransparentContext()) ||
(S->isClassScope() && !getLangOpts().CPlusPlus))
S = S->getParent();
return S;
}
static void LookupPredefedObjCSuperType(Sema &ThisSema, Scope *S,
IdentifierInfo *II) {
if (!II->isStr("objc_msgSendSuper"))
return;
ASTContext &Context = ThisSema.Context;
LookupResult Result(ThisSema, &Context.Idents.get("objc_super"),
SourceLocation(), Sema::LookupTagName);
ThisSema.LookupName(Result, S);
if (Result.getResultKind() == LookupResult::Found)
if (const TagDecl *TD = Result.getAsSingle<TagDecl>())
Context.setObjCSuperType(Context.getTagDeclType(TD));
}
NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
Scope *S, bool ForRedeclaration,
SourceLocation Loc) {
LookupPredefedObjCSuperType(*this, S, II);
Builtin::ID BID = (Builtin::ID)bid;
ASTContext::GetBuiltinTypeError Error;
QualType R = Context.GetBuiltinType(BID, Error);
switch (Error) {
case ASTContext::GE_None:
break;
case ASTContext::GE_Missing_stdio:
if (ForRedeclaration)
Diag(Loc, diag::warn_implicit_decl_requires_stdio)
<< Context.BuiltinInfo.GetName(BID);
return 0;
case ASTContext::GE_Missing_setjmp:
if (ForRedeclaration)
Diag(Loc, diag::warn_implicit_decl_requires_setjmp)
<< Context.BuiltinInfo.GetName(BID);
return 0;
case ASTContext::GE_Missing_ucontext:
if (ForRedeclaration)
Diag(Loc, diag::warn_implicit_decl_requires_ucontext)
<< Context.BuiltinInfo.GetName(BID);
return 0;
}
if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(BID)) {
Diag(Loc, diag::ext_implicit_lib_function_decl)
<< Context.BuiltinInfo.GetName(BID)
<< R;
if (Context.BuiltinInfo.getHeaderName(BID) &&
Diags.getDiagnosticLevel(diag::ext_implicit_lib_function_decl, Loc)
!= DiagnosticsEngine::Ignored)
Diag(Loc, diag::note_please_include_header)
<< Context.BuiltinInfo.getHeaderName(BID)
<< Context.BuiltinInfo.GetName(BID);
}
DeclContext *Parent = Context.getTranslationUnitDecl();
if (getLangOpts().CPlusPlus) {
LinkageSpecDecl *CLinkageDecl =
LinkageSpecDecl::Create(Context, Parent, Loc, Loc,
LinkageSpecDecl::lang_c, false);
CLinkageDecl->setImplicit();
Parent->addDecl(CLinkageDecl);
Parent = CLinkageDecl;
}
FunctionDecl *New = FunctionDecl::Create(Context,
Parent,
Loc, Loc, II, R, 0,
SC_Extern,
false,
true);
New->setImplicit();
if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(R)) {
SmallVector<ParmVarDecl*, 16> Params;
for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
ParmVarDecl *parm =
ParmVarDecl::Create(Context, New, SourceLocation(), SourceLocation(),
0, FT->getParamType(i), 0, SC_None, 0);
parm->setScopeInfo(0, i);
Params.push_back(parm);
}
New->setParams(Params);
}
AddKnownFunctionAttributes(New);
RegisterLocallyScopedExternCDecl(New, S);
DeclContext *SavedContext = CurContext;
CurContext = Parent;
PushOnScopeChains(New, TUScope);
CurContext = SavedContext;
return New;
}
static void filterNonConflictingPreviousDecls(ASTContext &context,
NamedDecl *decl,
LookupResult &previous){
if (!context.getLangOpts().Modules)
return;
if (previous.empty())
return;
LookupResult::Filter filter = previous.makeFilter();
while (filter.hasNext()) {
NamedDecl *old = filter.next();
if (!old->isHidden())
continue;
if (!old->isExternallyVisible())
filter.erase();
}
filter.done();
}
bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) {
QualType OldType;
if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old))
OldType = OldTypedef->getUnderlyingType();
else
OldType = Context.getTypeDeclType(Old);
QualType NewType = New->getUnderlyingType();
if (NewType->isVariablyModifiedType()) {
int Kind = isa<TypeAliasDecl>(Old) ? 1 : 0;
Diag(New->getLocation(), diag::err_redefinition_variably_modified_typedef)
<< Kind << NewType;
if (Old->getLocation().isValid())
Diag(Old->getLocation(), diag::note_previous_definition);
New->setInvalidDecl();
return true;
}
if (OldType != NewType &&
!OldType->isDependentType() &&
!NewType->isDependentType() &&
!Context.hasSameType(OldType, NewType)) {
int Kind = isa<TypeAliasDecl>(Old) ? 1 : 0;
Diag(New->getLocation(), diag::err_redefinition_different_typedef)
<< Kind << NewType << OldType;
if (Old->getLocation().isValid())
Diag(Old->getLocation(), diag::note_previous_definition);
New->setInvalidDecl();
return true;
}
return false;
}
void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) {
if (New->isInvalidDecl()) return;
if (getLangOpts().ObjC1) {
const IdentifierInfo *TypeID = New->getIdentifier();
switch (TypeID->getLength()) {
default: break;
case 2:
{
if (!TypeID->isStr("id"))
break;
QualType T = New->getUnderlyingType();
if (!T->isPointerType())
break;
if (!T->isVoidPointerType()) {
QualType PT = T->getAs<PointerType>()->getPointeeType();
if (!PT->isStructureType())
break;
}
Context.setObjCIdRedefinitionType(T);
New->setTypeForDecl(Context.getObjCIdType().getTypePtr());
return;
}
case 5:
if (!TypeID->isStr("Class"))
break;
Context.setObjCClassRedefinitionType(New->getUnderlyingType());
New->setTypeForDecl(Context.getObjCClassType().getTypePtr());
return;
case 3:
if (!TypeID->isStr("SEL"))
break;
Context.setObjCSelRedefinitionType(New->getUnderlyingType());
New->setTypeForDecl(Context.getObjCSelType().getTypePtr());
return;
}
}
TypeDecl *Old = OldDecls.getAsSingle<TypeDecl>();
if (!Old) {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
<< New->getDeclName();
NamedDecl *OldD = OldDecls.getRepresentativeDecl();
if (OldD->getLocation().isValid())
Diag(OldD->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
}
if (Old->isInvalidDecl())
return New->setInvalidDecl();
if (isIncompatibleTypedef(Old, New))
return;
if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Old)) {
New->setPreviousDecl(Typedef);
mergeDeclAttributes(New, Old);
}
if (getLangOpts().MicrosoftExt)
return;
if (getLangOpts().CPlusPlus) {
if (!isa<CXXRecordDecl>(CurContext))
return;
if (!isa<TypedefNameDecl>(Old))
return;
Diag(New->getLocation(), diag::err_redefinition)
<< New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
}
if (getLangOpts().Modules || getLangOpts().C11)
return;
if (getDiagnostics().getSuppressSystemWarnings() &&
(Context.getSourceManager().isInSystemHeader(Old->getLocation()) ||
Context.getSourceManager().isInSystemHeader(New->getLocation())))
return;
Diag(New->getLocation(), diag::warn_redefinition_of_typedef)
<< New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return;
}
static bool DeclHasAttr(const Decl *D, const Attr *A) {
const OwnershipAttr *OA = dyn_cast<OwnershipAttr>(A);
const AnnotateAttr *Ann = dyn_cast<AnnotateAttr>(A);
for (Decl::attr_iterator i = D->attr_begin(), e = D->attr_end(); i != e; ++i)
if ((*i)->getKind() == A->getKind()) {
if (Ann) {
if (Ann->getAnnotation() == cast<AnnotateAttr>(*i)->getAnnotation())
return true;
continue;
}
if (OA && isa<OwnershipAttr>(*i))
return OA->getOwnKind() == cast<OwnershipAttr>(*i)->getOwnKind();
return true;
}
return false;
}
static bool isAttributeTargetADefinition(Decl *D) {
if (VarDecl *VD = dyn_cast<VarDecl>(D))
return VD->isThisDeclarationADefinition();
if (TagDecl *TD = dyn_cast<TagDecl>(D))
return TD->isCompleteDefinition() || TD->isBeingDefined();
return true;
}
static bool mergeAlignedAttrs(Sema &S, NamedDecl *New, Decl *Old) {
AlignedAttr *OldAlignasAttr = 0;
AlignedAttr *OldStrictestAlignAttr = 0;
unsigned OldAlign = 0;
for (specific_attr_iterator<AlignedAttr>
I = Old->specific_attr_begin<AlignedAttr>(),
E = Old->specific_attr_end<AlignedAttr>(); I != E; ++I) {
if (I->isAlignmentDependent())
return false;
if (I->isAlignas())
OldAlignasAttr = *I;
unsigned Align = I->getAlignment(S.Context);
if (Align > OldAlign) {
OldAlign = Align;
OldStrictestAlignAttr = *I;
}
}
AlignedAttr *NewAlignasAttr = 0;
unsigned NewAlign = 0;
for (specific_attr_iterator<AlignedAttr>
I = New->specific_attr_begin<AlignedAttr>(),
E = New->specific_attr_end<AlignedAttr>(); I != E; ++I) {
if (I->isAlignmentDependent())
return false;
if (I->isAlignas())
NewAlignasAttr = *I;
unsigned Align = I->getAlignment(S.Context);
if (Align > NewAlign)
NewAlign = Align;
}
if (OldAlignasAttr && NewAlignasAttr && OldAlign != NewAlign) {
if (OldAlign == 0 || NewAlign == 0) {
QualType Ty;
if (ValueDecl *VD = dyn_cast<ValueDecl>(New))
Ty = VD->getType();
else
Ty = S.Context.getTagDeclType(cast<TagDecl>(New));
if (OldAlign == 0)
OldAlign = S.Context.getTypeAlign(Ty);
if (NewAlign == 0)
NewAlign = S.Context.getTypeAlign(Ty);
}
if (OldAlign != NewAlign) {
S.Diag(NewAlignasAttr->getLocation(), diag::err_alignas_mismatch)
<< (unsigned)S.Context.toCharUnitsFromBits(OldAlign).getQuantity()
<< (unsigned)S.Context.toCharUnitsFromBits(NewAlign).getQuantity();
S.Diag(OldAlignasAttr->getLocation(), diag::note_previous_declaration);
}
}
if (OldAlignasAttr && !NewAlignasAttr && isAttributeTargetADefinition(New)) {
S.Diag(New->getLocation(), diag::err_alignas_missing_on_definition)
<< OldAlignasAttr;
S.Diag(OldAlignasAttr->getLocation(), diag::note_alignas_on_declaration)
<< OldAlignasAttr;
}
bool AnyAdded = false;
if (OldAlign > NewAlign) {
AlignedAttr *Clone = OldStrictestAlignAttr->clone(S.Context);
Clone->setInherited(true);
New->addAttr(Clone);
AnyAdded = true;
}
if (OldAlignasAttr && !NewAlignasAttr &&
!(AnyAdded && OldStrictestAlignAttr->isAlignas())) {
AlignedAttr *Clone = OldAlignasAttr->clone(S.Context);
Clone->setInherited(true);
New->addAttr(Clone);
AnyAdded = true;
}
return AnyAdded;
}
static bool mergeDeclAttribute(Sema &S, NamedDecl *D, InheritableAttr *Attr,
bool Override) {
InheritableAttr *NewAttr = NULL;
unsigned AttrSpellingListIndex = Attr->getSpellingListIndex();
if (AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(Attr))
NewAttr = S.mergeAvailabilityAttr(D, AA->getRange(), AA->getPlatform(),
AA->getIntroduced(), AA->getDeprecated(),
AA->getObsoleted(), AA->getUnavailable(),
AA->getMessage(), Override,
AttrSpellingListIndex);
else if (VisibilityAttr *VA = dyn_cast<VisibilityAttr>(Attr))
NewAttr = S.mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility(),
AttrSpellingListIndex);
else if (TypeVisibilityAttr *VA = dyn_cast<TypeVisibilityAttr>(Attr))
NewAttr = S.mergeTypeVisibilityAttr(D, VA->getRange(), VA->getVisibility(),
AttrSpellingListIndex);
else if (DLLImportAttr *ImportA = dyn_cast<DLLImportAttr>(Attr))
NewAttr = S.mergeDLLImportAttr(D, ImportA->getRange(),
AttrSpellingListIndex);
else if (DLLExportAttr *ExportA = dyn_cast<DLLExportAttr>(Attr))
NewAttr = S.mergeDLLExportAttr(D, ExportA->getRange(),
AttrSpellingListIndex);
else if (FormatAttr *FA = dyn_cast<FormatAttr>(Attr))
NewAttr = S.mergeFormatAttr(D, FA->getRange(), FA->getType(),
FA->getFormatIdx(), FA->getFirstArg(),
AttrSpellingListIndex);
else if (SectionAttr *SA = dyn_cast<SectionAttr>(Attr))
NewAttr = S.mergeSectionAttr(D, SA->getRange(), SA->getName(),
AttrSpellingListIndex);
else if (isa<AlignedAttr>(Attr))
NewAttr = 0;
else if (Attr->duplicatesAllowed() || !DeclHasAttr(D, Attr))
NewAttr = cast<InheritableAttr>(Attr->clone(S.Context));
if (NewAttr) {
NewAttr->setInherited(true);
D->addAttr(NewAttr);
return true;
}
return false;
}
static const Decl *getDefinition(const Decl *D) {
if (const TagDecl *TD = dyn_cast<TagDecl>(D))
return TD->getDefinition();
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
const VarDecl *Def = VD->getDefinition();
if (Def)
return Def;
return VD->getActingDefinition();
}
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
const FunctionDecl* Def;
if (FD->isDefined(Def))
return Def;
}
return NULL;
}
static bool hasAttribute(const Decl *D, attr::Kind Kind) {
for (Decl::attr_iterator I = D->attr_begin(), E = D->attr_end();
I != E; ++I) {
Attr *Attribute = *I;
if (Attribute->getKind() == Kind)
return true;
}
return false;
}
static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
if (!New->hasAttrs())
return;
const Decl *Def = getDefinition(Old);
if (!Def || Def == New)
return;
AttrVec &NewAttributes = New->getAttrs();
for (unsigned I = 0, E = NewAttributes.size(); I != E;) {
const Attr *NewAttribute = NewAttributes[I];
if (isa<AliasAttr>(NewAttribute)) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(New))
S.CheckForFunctionRedefinition(FD, cast<FunctionDecl>(Def));
else {
VarDecl *VD = cast<VarDecl>(New);
unsigned Diag = cast<VarDecl>(Def)->isThisDeclarationADefinition() ==
VarDecl::TentativeDefinition
? diag::err_alias_after_tentative
: diag::err_redefinition;
S.Diag(VD->getLocation(), Diag) << VD->getDeclName();
S.Diag(Def->getLocation(), diag::note_previous_definition);
VD->setInvalidDecl();
}
++I;
continue;
}
if (const VarDecl *VD = dyn_cast<VarDecl>(Def)) {
if (VD->isThisDeclarationADefinition() != VarDecl::Definition) {
++I;
continue;
}
}
if (hasAttribute(Def, NewAttribute->getKind())) {
++I;
continue; }
if (isa<C11NoReturnAttr>(NewAttribute)) {
++I;
continue;
} else if (const AlignedAttr *AA = dyn_cast<AlignedAttr>(NewAttribute)) {
if (AA->isAlignas()) {
S.Diag(Def->getLocation(), diag::err_alignas_missing_on_definition)
<< AA;
S.Diag(NewAttribute->getLocation(), diag::note_alignas_on_declaration)
<< AA;
NewAttributes.erase(NewAttributes.begin() + I);
--E;
continue;
}
}
S.Diag(NewAttribute->getLocation(),
diag::warn_attribute_precede_definition);
S.Diag(Def->getLocation(), diag::note_previous_definition);
NewAttributes.erase(NewAttributes.begin() + I);
--E;
}
}
void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
AvailabilityMergeKind AMK) {
if (UsedAttr *OldAttr = Old->getMostRecentDecl()->getAttr<UsedAttr>()) {
UsedAttr *NewAttr = OldAttr->clone(Context);
NewAttr->setInherited(true);
New->addAttr(NewAttr);
}
if (!Old->hasAttrs() && !New->hasAttrs())
return;
checkNewAttributesAfterDef(*this, New, Old);
if (!Old->hasAttrs())
return;
bool foundAny = New->hasAttrs();
if (!foundAny) New->setAttrs(AttrVec());
for (specific_attr_iterator<InheritableAttr>
i = Old->specific_attr_begin<InheritableAttr>(),
e = Old->specific_attr_end<InheritableAttr>();
i != e; ++i) {
bool Override = false;
if (isa<DeprecatedAttr>(*i) ||
isa<UnavailableAttr>(*i) ||
isa<AvailabilityAttr>(*i)) {
switch (AMK) {
case AMK_None:
continue;
case AMK_Redeclaration:
break;
case AMK_Override:
Override = true;
break;
}
}
if (isa<UsedAttr>(*i))
continue;
if (mergeDeclAttribute(*this, New, *i, Override))
foundAny = true;
}
if (mergeAlignedAttrs(*this, New, Old))
foundAny = true;
if (!foundAny) New->dropAttrs();
}
static void mergeParamDeclAttributes(ParmVarDecl *newDecl,
const ParmVarDecl *oldDecl,
Sema &S) {
const CarriesDependencyAttr *CDA = newDecl->getAttr<CarriesDependencyAttr>();
if (CDA && !oldDecl->hasAttr<CarriesDependencyAttr>()) {
S.Diag(CDA->getLocation(),
diag::err_carries_dependency_missing_on_first_decl) << 1;
const FunctionDecl *FirstFD =
cast<FunctionDecl>(oldDecl->getDeclContext())->getFirstDecl();
const ParmVarDecl *FirstVD =
FirstFD->getParamDecl(oldDecl->getFunctionScopeIndex());
S.Diag(FirstVD->getLocation(),
diag::note_carries_dependency_missing_first_decl) << 1;
}
if (!oldDecl->hasAttrs())
return;
bool foundAny = newDecl->hasAttrs();
if (!foundAny) newDecl->setAttrs(AttrVec());
for (specific_attr_iterator<InheritableParamAttr>
i = oldDecl->specific_attr_begin<InheritableParamAttr>(),
e = oldDecl->specific_attr_end<InheritableParamAttr>(); i != e; ++i) {
if (!DeclHasAttr(newDecl, *i)) {
InheritableAttr *newAttr =
cast<InheritableParamAttr>((*i)->clone(S.Context));
newAttr->setInherited(true);
newDecl->addAttr(newAttr);
foundAny = true;
}
}
if (!foundAny) newDecl->dropAttrs();
}
namespace {
struct GNUCompatibleParamWarning {
ParmVarDecl *OldParm;
ParmVarDecl *NewParm;
QualType PromotedType;
};
}
Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) {
if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) {
if (Ctor->isDefaultConstructor())
return Sema::CXXDefaultConstructor;
if (Ctor->isCopyConstructor())
return Sema::CXXCopyConstructor;
if (Ctor->isMoveConstructor())
return Sema::CXXMoveConstructor;
} else if (isa<CXXDestructorDecl>(MD)) {
return Sema::CXXDestructor;
} else if (MD->isCopyAssignmentOperator()) {
return Sema::CXXCopyAssignment;
} else if (MD->isMoveAssignmentOperator()) {
return Sema::CXXMoveAssignment;
}
return Sema::CXXInvalid;
}
static bool canRedefineFunction(const FunctionDecl *FD,
const LangOptions& LangOpts) {
return ((FD->hasAttr<GNUInlineAttr>() || LangOpts.GNUInline) &&
!LangOpts.CPlusPlus &&
FD->isInlineSpecified() &&
FD->getStorageClass() == SC_Extern);
}
const AttributedType *Sema::getCallingConvAttributedType(QualType T) const {
const AttributedType *AT = T->getAs<AttributedType>();
while (AT && !AT->isCallingConv())
AT = AT->getModifiedType()->getAs<AttributedType>();
return AT;
}
template <typename T>
static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) {
const DeclContext *DC = Old->getDeclContext();
if (DC->isRecord())
return false;
LanguageLinkage OldLinkage = Old->getLanguageLinkage();
if (OldLinkage == CXXLanguageLinkage && New->isInExternCContext())
return true;
if (OldLinkage == CLanguageLinkage && New->isInExternCXXContext())
return true;
return false;
}
bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
bool MergeTypeWithOld) {
FunctionDecl *Old = OldD->getAsFunction();
if (!Old) {
if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(OldD)) {
if (New->getFriendObjectKind()) {
Diag(New->getLocation(), diag::err_using_decl_friend);
Diag(Shadow->getTargetDecl()->getLocation(),
diag::note_using_decl_target);
Diag(Shadow->getUsingDecl()->getLocation(),
diag::note_using_decl) << 0;
return true;
}
Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
Diag(Shadow->getTargetDecl()->getLocation(),
diag::note_using_decl_target);
Diag(Shadow->getUsingDecl()->getLocation(),
diag::note_using_decl) << 0;
return true;
}
Diag(New->getLocation(), diag::err_redefinition_different_kind)
<< New->getDeclName();
Diag(OldD->getLocation(), diag::note_previous_definition);
return true;
}
if (Old->isInvalidDecl())
return true;
diag::kind PrevDiag;
if (Old->isThisDeclarationADefinition())
PrevDiag = diag::note_previous_definition;
else if (Old->isImplicit())
PrevDiag = diag::note_previous_implicit_declaration;
else
PrevDiag = diag::note_previous_declaration;
if (!isa<CXXMethodDecl>(New) && !isa<CXXMethodDecl>(Old) &&
New->getStorageClass() == SC_Static &&
Old->hasExternalFormalLinkage() &&
!New->getTemplateSpecializationInfo() &&
!canRedefineFunction(Old, getLangOpts())) {
if (getLangOpts().MicrosoftExt) {
Diag(New->getLocation(), diag::warn_static_non_static) << New;
Diag(Old->getLocation(), PrevDiag);
} else {
Diag(New->getLocation(), diag::err_static_non_static) << New;
Diag(Old->getLocation(), PrevDiag);
return true;
}
}
QualType OldQType = Context.getCanonicalType(Old->getType());
QualType NewQType = Context.getCanonicalType(New->getType());
const FunctionType *OldType = cast<FunctionType>(OldQType);
const FunctionType *NewType = cast<FunctionType>(NewQType);
FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo();
FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo();
bool RequiresAdjustment = false;
if (OldTypeInfo.getCC() != NewTypeInfo.getCC()) {
FunctionDecl *First = Old->getFirstDecl();
const FunctionType *FT =
First->getType().getCanonicalType()->castAs<FunctionType>();
FunctionType::ExtInfo FI = FT->getExtInfo();
bool NewCCExplicit = getCallingConvAttributedType(New->getType());
if (!NewCCExplicit) {
NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
RequiresAdjustment = true;
} else {
bool FirstCCExplicit = getCallingConvAttributedType(First->getType());
Diag(New->getLocation(), diag::err_cconv_change)
<< FunctionType::getNameForCallConv(NewTypeInfo.getCC())
<< !FirstCCExplicit
<< (!FirstCCExplicit ? "" :
FunctionType::getNameForCallConv(FI.getCC()));
Diag(First->getLocation(), diag::note_previous_declaration);
return true;
}
}
if (OldTypeInfo.getNoReturn() && !NewTypeInfo.getNoReturn()) {
NewTypeInfo = NewTypeInfo.withNoReturn(true);
RequiresAdjustment = true;
}
if (OldTypeInfo.getHasRegParm() != NewTypeInfo.getHasRegParm() ||
OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) {
if (NewTypeInfo.getHasRegParm()) {
Diag(New->getLocation(), diag::err_regparm_mismatch)
<< NewType->getRegParmType()
<< OldType->getRegParmType();
Diag(Old->getLocation(), diag::note_previous_declaration);
return true;
}
NewTypeInfo = NewTypeInfo.withRegParm(OldTypeInfo.getRegParm());
RequiresAdjustment = true;
}
if (OldTypeInfo.getProducesResult() != NewTypeInfo.getProducesResult()) {
if (NewTypeInfo.getProducesResult()) {
Diag(New->getLocation(), diag::err_returns_retained_mismatch);
Diag(Old->getLocation(), diag::note_previous_declaration);
return true;
}
NewTypeInfo = NewTypeInfo.withProducesResult(true);
RequiresAdjustment = true;
}
if (RequiresAdjustment) {
const FunctionType *AdjustedType = New->getType()->getAs<FunctionType>();
AdjustedType = Context.adjustFunctionType(AdjustedType, NewTypeInfo);
New->setType(QualType(AdjustedType, 0));
NewQType = Context.getCanonicalType(New->getType());
NewType = cast<FunctionType>(NewQType);
}
if (!Old->isInlined() && New->isInlined() &&
!New->hasAttr<GNUInlineAttr>() &&
(getLangOpts().CPlusPlus || !getLangOpts().GNUInline) &&
Old->isUsed(false) &&
!Old->isDefined() && !New->isThisDeclarationADefinition())
UndefinedButUsed.insert(std::make_pair(Old->getCanonicalDecl(),
SourceLocation()));
if (New->hasAttr<GNUInlineAttr>() &&
Old->isInlined() && !Old->hasAttr<GNUInlineAttr>()) {
UndefinedButUsed.erase(Old->getCanonicalDecl());
}
if (getLangOpts().CPlusPlus) {
QualType OldDeclaredReturnType =
(Old->getTypeSourceInfo()
? Old->getTypeSourceInfo()->getType()->castAs<FunctionType>()
: OldType)->getReturnType();
QualType NewDeclaredReturnType =
(New->getTypeSourceInfo()
? New->getTypeSourceInfo()->getType()->castAs<FunctionType>()
: NewType)->getReturnType();
QualType ResQT;
if (!Context.hasSameType(OldDeclaredReturnType, NewDeclaredReturnType) &&
!((NewQType->isDependentType() || OldQType->isDependentType()) &&
New->isLocalExternDecl())) {
if (NewDeclaredReturnType->isObjCObjectPointerType() &&
OldDeclaredReturnType->isObjCObjectPointerType())
ResQT = Context.mergeObjCGCQualifiers(NewQType, OldQType);
if (ResQT.isNull()) {
if (New->isCXXClassMember() && New->isOutOfLine())
Diag(New->getLocation(),
diag::err_member_def_does_not_match_ret_type) << New;
else
Diag(New->getLocation(), diag::err_ovl_diff_return_type);
Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
return true;
}
else
NewQType = ResQT;
}
QualType OldReturnType = OldType->getReturnType();
QualType NewReturnType = cast<FunctionType>(NewQType)->getReturnType();
if (OldReturnType != NewReturnType) {
AutoType *OldAT = Old->getReturnType()->getContainedAutoType();
if (OldAT && OldAT->isDeduced()) {
New->setType(
SubstAutoType(New->getType(),
OldAT->isDependentType() ? Context.DependentTy
: OldAT->getDeducedType()));
NewQType = Context.getCanonicalType(
SubstAutoType(NewQType,
OldAT->isDependentType() ? Context.DependentTy
: OldAT->getDeducedType()));
}
}
const CXXMethodDecl *OldMethod = dyn_cast<CXXMethodDecl>(Old);
CXXMethodDecl *NewMethod = dyn_cast<CXXMethodDecl>(New);
if (OldMethod && NewMethod) {
NewMethod->setTrivial(OldMethod->isTrivial());
bool IsClassScopeExplicitSpecialization =
OldMethod->isFunctionTemplateSpecialization() &&
NewMethod->isFunctionTemplateSpecialization();
bool isFriend = NewMethod->getFriendObjectKind();
if (!isFriend && NewMethod->getLexicalDeclContext()->isRecord() &&
!IsClassScopeExplicitSpecialization) {
if (OldMethod->isStatic() != NewMethod->isStatic()) {
Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member);
Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
return true;
}
if (ActiveTemplateInstantiations.empty()) {
unsigned NewDiag;
if (isa<CXXConstructorDecl>(OldMethod))
NewDiag = diag::err_constructor_redeclared;
else if (isa<CXXDestructorDecl>(NewMethod))
NewDiag = diag::err_destructor_redeclared;
else if (isa<CXXConversionDecl>(NewMethod))
NewDiag = diag::err_conv_function_redeclared;
else
NewDiag = diag::err_member_redeclared;
Diag(New->getLocation(), NewDiag);
} else {
Diag(New->getLocation(), diag::err_member_redeclared_in_instantiation)
<< New << New->getType();
}
Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
} else if (OldMethod->isImplicit()) {
if (isFriend) {
NewMethod->setImplicit();
} else {
Diag(NewMethod->getLocation(),
diag::err_definition_of_implicitly_declared_member)
<< New << getSpecialMember(OldMethod);
return true;
}
} else if (OldMethod->isExplicitlyDefaulted() && !isFriend) {
Diag(NewMethod->getLocation(),
diag::err_definition_of_explicitly_defaulted_member)
<< getSpecialMember(OldMethod);
return true;
}
}
const CXX11NoReturnAttr *NRA = New->getAttr<CXX11NoReturnAttr>();
if (NRA && !Old->hasAttr<CXX11NoReturnAttr>()) {
Diag(NRA->getLocation(), diag::err_noreturn_missing_on_first_decl);
Diag(Old->getFirstDecl()->getLocation(),
diag::note_noreturn_missing_first_decl);
}
const CarriesDependencyAttr *CDA = New->getAttr<CarriesDependencyAttr>();
if (CDA && !Old->hasAttr<CarriesDependencyAttr>()) {
Diag(CDA->getLocation(),
diag::err_carries_dependency_missing_on_first_decl) << 0;
Diag(Old->getFirstDecl()->getLocation(),
diag::note_carries_dependency_missing_first_decl) << 0;
}
QualType OldQTypeForComparison = OldQType;
if (!OldTypeInfo.getNoReturn() && NewTypeInfo.getNoReturn()) {
assert(OldQType == QualType(OldType, 0));
const FunctionType *OldTypeForComparison
= Context.adjustFunctionType(OldType, OldTypeInfo.withNoReturn(true));
OldQTypeForComparison = QualType(OldTypeForComparison, 0);
assert(OldQTypeForComparison.isCanonical());
}
if (haveIncompatibleLanguageLinkages(Old, New)) {
if (New->getFriendObjectKind() != Decl::FOK_None) {
Diag(New->getLocation(), diag::ext_retained_language_linkage) << New;
Diag(Old->getLocation(), PrevDiag);
} else {
Diag(New->getLocation(), diag::err_different_language_linkage) << New;
Diag(Old->getLocation(), PrevDiag);
return true;
}
}
if (OldQTypeForComparison == NewQType)
return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld);
if ((NewQType->isDependentType() || OldQType->isDependentType()) &&
New->isLocalExternDecl()) {
return false;
}
}
if (!getLangOpts().CPlusPlus &&
Context.typesAreCompatible(OldQType, NewQType)) {
const FunctionType *OldFuncType = OldQType->getAs<FunctionType>();
const FunctionType *NewFuncType = NewQType->getAs<FunctionType>();
const FunctionProtoType *OldProto = 0;
if (MergeTypeWithOld && isa<FunctionNoProtoType>(NewFuncType) &&
(OldProto = dyn_cast<FunctionProtoType>(OldFuncType))) {
assert(!OldProto->hasExceptionSpec() && "Exception spec in C");
SmallVector<QualType, 16> ParamTypes(OldProto->param_type_begin(),
OldProto->param_type_end());
NewQType =
Context.getFunctionType(NewFuncType->getReturnType(), ParamTypes,
OldProto->getExtProtoInfo());
New->setType(NewQType);
New->setHasInheritedPrototype();
SmallVector<ParmVarDecl*, 16> Params;
for (FunctionProtoType::param_type_iterator
ParamType = OldProto->param_type_begin(),
ParamEnd = OldProto->param_type_end();
ParamType != ParamEnd; ++ParamType) {
ParmVarDecl *Param = ParmVarDecl::Create(Context, New,
SourceLocation(),
SourceLocation(), 0,
*ParamType, 0,
SC_None,
0);
Param->setScopeInfo(0, Params.size());
Param->setImplicit();
Params.push_back(Param);
}
New->setParams(Params);
}
return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld);
}
if (!getLangOpts().CPlusPlus &&
Old->hasPrototype() && !New->hasPrototype() &&
New->getType()->getAs<FunctionProtoType>() &&
Old->getNumParams() == New->getNumParams()) {
SmallVector<QualType, 16> ArgTypes;
SmallVector<GNUCompatibleParamWarning, 16> Warnings;
const FunctionProtoType *OldProto
= Old->getType()->getAs<FunctionProtoType>();
const FunctionProtoType *NewProto
= New->getType()->getAs<FunctionProtoType>();
QualType MergedReturn = Context.mergeTypes(OldProto->getReturnType(),
NewProto->getReturnType());
bool LooseCompatible = !MergedReturn.isNull();
for (unsigned Idx = 0, End = Old->getNumParams();
LooseCompatible && Idx != End; ++Idx) {
ParmVarDecl *OldParm = Old->getParamDecl(Idx);
ParmVarDecl *NewParm = New->getParamDecl(Idx);
if (Context.typesAreCompatible(OldParm->getType(),
NewProto->getParamType(Idx))) {
ArgTypes.push_back(NewParm->getType());
} else if (Context.typesAreCompatible(OldParm->getType(),
NewParm->getType(),
true)) {
GNUCompatibleParamWarning Warn = { OldParm, NewParm,
NewProto->getParamType(Idx) };
Warnings.push_back(Warn);
ArgTypes.push_back(NewParm->getType());
} else
LooseCompatible = false;
}
if (LooseCompatible) {
for (unsigned Warn = 0; Warn < Warnings.size(); ++Warn) {
Diag(Warnings[Warn].NewParm->getLocation(),
diag::ext_param_promoted_not_compatible_with_prototype)
<< Warnings[Warn].PromotedType
<< Warnings[Warn].OldParm->getType();
if (Warnings[Warn].OldParm->getLocation().isValid())
Diag(Warnings[Warn].OldParm->getLocation(),
diag::note_previous_declaration);
}
if (MergeTypeWithOld)
New->setType(Context.getFunctionType(MergedReturn, ArgTypes,
OldProto->getExtProtoInfo()));
return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld);
}
}
unsigned BuiltinID;
if (Old->isImplicit() && (BuiltinID = Old->getBuiltinID())) {
if (Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) {
Diag(New->getLocation(), diag::warn_redecl_library_builtin) << New;
Diag(Old->getLocation(), diag::note_previous_builtin_declaration)
<< Old << Old->getType();
if (!New->getLexicalDeclContext()->isFunctionOrMethod())
New->getIdentifier()->setBuiltinID(Builtin::NotBuiltin);
return false;
}
PrevDiag = diag::note_previous_builtin_declaration;
}
Diag(New->getLocation(), diag::err_conflicting_types) << New->getDeclName();
Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
return true;
}
bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
Scope *S, bool MergeTypeWithOld) {
mergeDeclAttributes(New, Old);
if (Old->isPure())
New->setPure();
if (Old->getMostRecentDecl()->isUsed(false))
New->setIsUsed();
if (New->getNumParams() == Old->getNumParams())
for (unsigned i = 0, e = New->getNumParams(); i != e; ++i)
mergeParamDeclAttributes(New->getParamDecl(i), Old->getParamDecl(i),
*this);
if (getLangOpts().CPlusPlus)
return MergeCXXFunctionDecl(New, Old, S);
QualType Merged = Context.mergeTypes(Old->getType(), New->getType());
if (!Merged.isNull() && MergeTypeWithOld)
New->setType(Merged);
return false;
}
void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
ObjCMethodDecl *oldMethod) {
AvailabilityMergeKind MergeKind =
isa<ObjCImplDecl>(newMethod->getDeclContext()) ? AMK_Redeclaration
: AMK_Override;
mergeDeclAttributes(newMethod, oldMethod, MergeKind);
ObjCMethodDecl::param_const_iterator oi = oldMethod->param_begin(),
oe = oldMethod->param_end();
for (ObjCMethodDecl::param_iterator
ni = newMethod->param_begin(), ne = newMethod->param_end();
ni != ne && oi != oe; ++ni, ++oi)
mergeParamDeclAttributes(*ni, *oi, *this);
CheckObjCMethodOverride(newMethod, oldMethod);
}
void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old,
bool MergeTypeWithOld) {
if (New->isInvalidDecl() || Old->isInvalidDecl())
return;
QualType MergedT;
if (getLangOpts().CPlusPlus) {
if (New->getType()->isUndeducedType()) {
return;
} else if (Context.hasSameType(New->getType(), Old->getType())) {
return MergeVarDeclExceptionSpecs(New, Old);
}
else if (Old->getType()->isIncompleteArrayType() &&
New->getType()->isArrayType()) {
const ArrayType *OldArray = Context.getAsArrayType(Old->getType());
const ArrayType *NewArray = Context.getAsArrayType(New->getType());
if (Context.hasSameType(OldArray->getElementType(),
NewArray->getElementType()))
MergedT = New->getType();
} else if (Old->getType()->isArrayType() &&
New->getType()->isIncompleteArrayType()) {
const ArrayType *OldArray = Context.getAsArrayType(Old->getType());
const ArrayType *NewArray = Context.getAsArrayType(New->getType());
if (Context.hasSameType(OldArray->getElementType(),
NewArray->getElementType()))
MergedT = Old->getType();
} else if (New->getType()->isObjCObjectPointerType() &&
Old->getType()->isObjCObjectPointerType()) {
MergedT = Context.mergeObjCGCQualifiers(New->getType(),
Old->getType());
}
} else {
MergedT = Context.mergeTypes(New->getType(), Old->getType());
}
if (MergedT.isNull()) {
if ((New->getType()->isDependentType() ||
Old->getType()->isDependentType()) && New->isLocalVarDecl()) {
if (!New->getType()->isDependentType() && MergeTypeWithOld)
New->setType(Context.DependentTy);
return;
}
Diag(New->getLocation(), diag::err_redefinition_different_type)
<< New->getDeclName() << New->getType() << Old->getType();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
}
if (MergeTypeWithOld)
New->setType(MergedT);
}
static bool mergeTypeWithPrevious(Sema &S, VarDecl *NewVD, VarDecl *OldVD,
LookupResult &Previous) {
if (Previous.isShadowed())
return false;
if (S.getLangOpts().CPlusPlus) {
return NewVD->isPreviousDeclInSameBlockScope() ||
(!OldVD->getLexicalDeclContext()->isFunctionOrMethod() &&
!NewVD->getLexicalDeclContext()->isFunctionOrMethod());
} else {
return !OldVD->getLexicalDeclContext()->isFunctionOrMethod() ||
OldVD->getLexicalDeclContext() == NewVD->getLexicalDeclContext();
}
}
void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
if (New->isInvalidDecl())
return;
VarTemplateDecl *NewTemplate = New->getDescribedVarTemplate();
VarDecl *Old = 0;
VarTemplateDecl *OldTemplate = 0;
if (Previous.isSingleResult()) {
if (NewTemplate) {
OldTemplate = dyn_cast<VarTemplateDecl>(Previous.getFoundDecl());
Old = OldTemplate ? OldTemplate->getTemplatedDecl() : 0;
} else
Old = dyn_cast<VarDecl>(Previous.getFoundDecl());
}
if (!Old) {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
<< New->getDeclName();
Diag(Previous.getRepresentativeDecl()->getLocation(),
diag::note_previous_definition);
return New->setInvalidDecl();
}
if (!shouldLinkPossiblyHiddenDecl(Old, New))
return;
if (NewTemplate &&
!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
OldTemplate->getTemplateParameters(),
true, TPL_TemplateMatch))
return;
if (Old->isStaticDataMember() && !New->isOutOfLine()) {
Diag(New->getLocation(), diag::err_duplicate_member)
<< New->getIdentifier();
Diag(Old->getLocation(), diag::note_previous_declaration);
New->setInvalidDecl();
}
mergeDeclAttributes(New, Old);
if (New->hasAttr<WeakImportAttr>() &&
Old->getStorageClass() == SC_None &&
!Old->hasAttr<WeakImportAttr>()) {
Diag(New->getLocation(), diag::warn_weak_import) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
New->dropAttr<WeakImportAttr>();
}
MergeVarDeclTypes(New, Old, mergeTypeWithPrevious(*this, New, Old, Previous));
if (New->isInvalidDecl())
return;
if (New->getStorageClass() == SC_Static &&
!New->isStaticDataMember() &&
Old->hasExternalFormalLinkage()) {
Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
}
if (New->hasExternalStorage() && Old->hasLinkage())
;
else if (New->getCanonicalDecl()->getStorageClass() != SC_Static &&
!New->isStaticDataMember() &&
Old->getCanonicalDecl()->getStorageClass() == SC_Static) {
Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
}
if (New->hasExternalStorage() &&
!Old->hasLinkage() && Old->isLocalVarDecl()) {
Diag(New->getLocation(), diag::err_extern_non_extern) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
}
if (Old->hasLinkage() && New->isLocalVarDecl() &&
!New->hasExternalStorage()) {
Diag(New->getLocation(), diag::err_non_extern_extern) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
}
if (!New->hasExternalStorage() && !New->isFileVarDecl() &&
!(Old->getLexicalDeclContext()->isRecord() &&
!New->getLexicalDeclContext()->isRecord())) {
Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
}
if (New->getTLSKind() != Old->getTLSKind()) {
if (!Old->getTLSKind()) {
Diag(New->getLocation(), diag::err_thread_non_thread) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_declaration);
} else if (!New->getTLSKind()) {
Diag(New->getLocation(), diag::err_non_thread_thread) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_declaration);
} else {
Diag(New->getLocation(), diag::err_thread_thread_different_kind)
<< New->getDeclName() << (New->getTLSKind() == VarDecl::TLS_Dynamic);
Diag(Old->getLocation(), diag::note_previous_declaration);
}
}
const VarDecl *Def;
if (getLangOpts().CPlusPlus &&
New->isThisDeclarationADefinition() == VarDecl::Definition &&
(Def = Old->getDefinition())) {
Diag(New->getLocation(), diag::err_redefinition) << New;
Diag(Def->getLocation(), diag::note_previous_definition);
New->setInvalidDecl();
return;
}
if (haveIncompatibleLanguageLinkages(Old, New)) {
Diag(New->getLocation(), diag::err_different_language_linkage) << New;
Diag(Old->getLocation(), diag::note_previous_definition);
New->setInvalidDecl();
return;
}
if (Old->getMostRecentDecl()->isUsed(false))
New->setIsUsed();
New->setPreviousDecl(Old);
if (NewTemplate)
NewTemplate->setPreviousDecl(OldTemplate);
New->setAccess(Old->getAccess());
if (NewTemplate)
NewTemplate->setAccess(New->getAccess());
}
Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
DeclSpec &DS) {
return ParsedFreeStandingDeclSpec(S, AS, DS, MultiTemplateParamsArg());
}
static void HandleTagNumbering(Sema &S, const TagDecl *Tag) {
if (!S.Context.getLangOpts().CPlusPlus)
return;
if (isa<CXXRecordDecl>(Tag->getParent())) {
if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl())
return;
MangleNumberingContext &MCtx =
S.Context.getManglingNumberContext(Tag->getParent());
S.Context.setManglingNumber(Tag, MCtx.getManglingNumber(Tag));
return;
}
Decl *ManglingContextDecl;
if (MangleNumberingContext *MCtx =
S.getCurrentMangleNumberContext(Tag->getDeclContext(),
ManglingContextDecl)) {
S.Context.setManglingNumber(Tag, MCtx->getManglingNumber(Tag));
}
}
Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
DeclSpec &DS,
MultiTemplateParamsArg TemplateParams,
bool IsExplicitInstantiation) {
Decl *TagD = 0;
TagDecl *Tag = 0;
if (DS.getTypeSpecType() == DeclSpec::TST_class ||
DS.getTypeSpecType() == DeclSpec::TST_struct ||
DS.getTypeSpecType() == DeclSpec::TST_interface ||
DS.getTypeSpecType() == DeclSpec::TST_union ||
DS.getTypeSpecType() == DeclSpec::TST_enum) {
TagD = DS.getRepAsDecl();
if (!TagD) return 0;
if (isa<TagDecl>(TagD))
Tag = cast<TagDecl>(TagD);
else if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(TagD))
Tag = CTD->getTemplatedDecl();
}
if (Tag) {
HandleTagNumbering(*this, Tag);
Tag->setFreeStanding();
if (Tag->isInvalidDecl())
return Tag;
}
if (unsigned TypeQuals = DS.getTypeQualifiers()) {
if (TypeQuals & DeclSpec::TQ_restrict)
Diag(DS.getRestrictSpecLoc(),
diag::err_typecheck_invalid_restrict_not_pointer_noarg)
<< DS.getSourceRange();
}
if (DS.isConstexprSpecified()) {
if (Tag)
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_tag)
<< (DS.getTypeSpecType() == DeclSpec::TST_class ? 0 :
DS.getTypeSpecType() == DeclSpec::TST_struct ? 1 :
DS.getTypeSpecType() == DeclSpec::TST_interface ? 2 :
DS.getTypeSpecType() == DeclSpec::TST_union ? 3 : 4);
else
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_no_declarators);
return TagD;
}
DiagnoseFunctionSpecifiers(DS);
if (DS.isFriendSpecified()) {
if (TagD && !Tag)
return 0;
return ActOnFriendTypeDecl(S, DS, TemplateParams);
}
CXXScopeSpec &SS = DS.getTypeSpecScope();
bool IsExplicitSpecialization =
!TemplateParams.empty() && TemplateParams.back()->size() == 0;
if (Tag && SS.isNotEmpty() && !Tag->isCompleteDefinition() &&
!IsExplicitInstantiation && !IsExplicitSpecialization) {
Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier)
<< (DS.getTypeSpecType() == DeclSpec::TST_class ? 0 :
DS.getTypeSpecType() == DeclSpec::TST_struct ? 1 :
DS.getTypeSpecType() == DeclSpec::TST_interface ? 2 :
DS.getTypeSpecType() == DeclSpec::TST_union ? 3 : 4)
<< SS.getRange();
return 0;
}
bool DeclaresAnything = true;
if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
if (!Record->getDeclName() && Record->isCompleteDefinition() &&
DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
if (getLangOpts().CPlusPlus ||
Record->getDeclContext()->isRecord())
return BuildAnonymousStructOrUnion(S, DS, AS, Record, Context.getPrintingPolicy());
DeclaresAnything = false;
}
}
if (getLangOpts().MicrosoftExt && !getLangOpts().CPlusPlus &&
CurContext->isRecord() &&
DS.getStorageClassSpec() == DeclSpec::SCS_unspecified) {
RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag);
if ((Record && Record->getDeclName() && !Record->isCompleteDefinition()) ||
(DS.getTypeSpecType() == DeclSpec::TST_typename &&
DS.getRepAsType().get()->isStructureType())) {
Diag(DS.getLocStart(), diag::ext_ms_anonymous_struct)
<< DS.getSourceRange();
return BuildMicrosoftCAnonymousStruct(S, DS, Record);
}
}
if (DS.getTypeSpecType() == DeclSpec::TST_error ||
(TagD && TagD->isInvalidDecl()))
return TagD;
if (getLangOpts().CPlusPlus &&
DS.getStorageClassSpec() != DeclSpec::SCS_typedef)
if (EnumDecl *Enum = dyn_cast_or_null<EnumDecl>(Tag))
if (Enum->enumerator_begin() == Enum->enumerator_end() &&
!Enum->getIdentifier() && !Enum->isInvalidDecl())
DeclaresAnything = false;
if (!DS.isMissingDeclaratorOk()) {
if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef)
Diag(DS.getLocStart(), diag::ext_typedef_without_a_name)
<< DS.getSourceRange();
else
DeclaresAnything = false;
}
if (DS.isModulePrivateSpecified() &&
Tag && Tag->getDeclContext()->isFunctionOrMethod())
Diag(DS.getModulePrivateSpecLoc(), diag::err_module_private_local_class)
<< Tag->getTagKind()
<< FixItHint::CreateRemoval(DS.getModulePrivateSpecLoc());
ActOnDocumentableDecl(TagD);
if (!DeclaresAnything) {
Diag(DS.getLocStart(), diag::ext_no_declarators) << DS.getSourceRange();
return TagD;
}
unsigned DiagID = diag::warn_standalone_specifier;
if (getLangOpts().CPlusPlus)
DiagID = diag::ext_standalone_specifier;
if (DeclSpec::SCS SCS = DS.getStorageClassSpec())
if (!DS.isExternInLinkageSpec() && SCS != DeclSpec::SCS_typedef)
Diag(DS.getStorageClassSpecLoc(), DiagID)
<< DeclSpec::getSpecifierName(SCS);
if (DeclSpec::TSCS TSCS = DS.getThreadStorageClassSpec())
Diag(DS.getThreadStorageClassSpecLoc(), DiagID)
<< DeclSpec::getSpecifierName(TSCS);
if (DS.getTypeQualifiers()) {
if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
Diag(DS.getConstSpecLoc(), DiagID) << "const";
if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
Diag(DS.getConstSpecLoc(), DiagID) << "volatile";
if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
Diag(DS.getAtomicSpecLoc(), DiagID) << "_Atomic";
}
if (!DS.getAttributes().empty()) {
DeclSpec::TST TypeSpecType = DS.getTypeSpecType();
if (TypeSpecType == DeclSpec::TST_class ||
TypeSpecType == DeclSpec::TST_struct ||
TypeSpecType == DeclSpec::TST_interface ||
TypeSpecType == DeclSpec::TST_union ||
TypeSpecType == DeclSpec::TST_enum) {
AttributeList* attrs = DS.getAttributes().getList();
while (attrs) {
Diag(attrs->getLoc(), diag::warn_declspec_attribute_ignored)
<< attrs->getName()
<< (TypeSpecType == DeclSpec::TST_class ? 0 :
TypeSpecType == DeclSpec::TST_struct ? 1 :
TypeSpecType == DeclSpec::TST_union ? 2 :
TypeSpecType == DeclSpec::TST_interface ? 3 : 4);
attrs = attrs->getNext();
}
}
}
return TagD;
}
static bool CheckAnonMemberRedeclaration(Sema &SemaRef,
Scope *S,
DeclContext *Owner,
DeclarationName Name,
SourceLocation NameLoc,
unsigned diagnostic) {
LookupResult R(SemaRef, Name, NameLoc, Sema::LookupMemberName,
Sema::ForRedeclaration);
if (!SemaRef.LookupName(R, S)) return false;
if (R.getAsSingle<TagDecl>())
return false;
NamedDecl *PrevDecl = R.getRepresentativeDecl()->getUnderlyingDecl();
assert(PrevDecl && "Expected a non-null Decl");
if (!SemaRef.isDeclInScope(PrevDecl, Owner, S))
return false;
SemaRef.Diag(NameLoc, diagnostic) << Name;
SemaRef.Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
return true;
}
static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
DeclContext *Owner,
RecordDecl *AnonRecord,
AccessSpecifier AS,
SmallVectorImpl<NamedDecl *> &Chaining,
bool MSAnonStruct) {
unsigned diagKind
= AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl
: diag::err_anonymous_struct_member_redecl;
bool Invalid = false;
for (RecordDecl::decl_iterator D = AnonRecord->decls_begin(),
DEnd = AnonRecord->decls_end();
D != DEnd; ++D) {
if ((isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D)) &&
cast<NamedDecl>(*D)->getDeclName()) {
ValueDecl *VD = cast<ValueDecl>(*D);
if (CheckAnonMemberRedeclaration(SemaRef, S, Owner, VD->getDeclName(),
VD->getLocation(), diagKind)) {
Invalid = true;
} else {
unsigned OldChainingSize = Chaining.size();
if (IndirectFieldDecl *IF = dyn_cast<IndirectFieldDecl>(VD))
for (IndirectFieldDecl::chain_iterator PI = IF->chain_begin(),
PE = IF->chain_end(); PI != PE; ++PI)
Chaining.push_back(*PI);
else
Chaining.push_back(VD);
assert(Chaining.size() >= 2);
NamedDecl **NamedChain =
new (SemaRef.Context)NamedDecl*[Chaining.size()];
for (unsigned i = 0; i < Chaining.size(); i++)
NamedChain[i] = Chaining[i];
IndirectFieldDecl* IndirectField =
IndirectFieldDecl::Create(SemaRef.Context, Owner, VD->getLocation(),
VD->getIdentifier(), VD->getType(),
NamedChain, Chaining.size());
IndirectField->setAccess(AS);
IndirectField->setImplicit();
SemaRef.PushOnScopeChains(IndirectField, S);
if (AS != AS_none) IndirectField->setAccess(AS);
Chaining.resize(OldChainingSize);
}
}
}
return Invalid;
}
static StorageClass
StorageClassSpecToVarDeclStorageClass(const DeclSpec &DS) {
DeclSpec::SCS StorageClassSpec = DS.getStorageClassSpec();
assert(StorageClassSpec != DeclSpec::SCS_typedef &&
"Parser allowed 'typedef' as storage class VarDecl.");
switch (StorageClassSpec) {
case DeclSpec::SCS_unspecified: return SC_None;
case DeclSpec::SCS_extern:
if (DS.isExternInLinkageSpec())
return SC_None;
return SC_Extern;
case DeclSpec::SCS_static: return SC_Static;
case DeclSpec::SCS_auto: return SC_Auto;
case DeclSpec::SCS_register: return SC_Register;
case DeclSpec::SCS_private_extern: return SC_PrivateExtern;
case DeclSpec::SCS_mutable: case DeclSpec::SCS_typedef: return SC_None;
}
llvm_unreachable("unknown storage class specifier");
}
static SourceLocation findDefaultInitializer(const CXXRecordDecl *Record) {
assert(Record->hasInClassInitializer());
for (DeclContext::decl_iterator I = Record->decls_begin(),
E = Record->decls_end();
I != E; ++I) {
FieldDecl *FD = dyn_cast<FieldDecl>(*I);
if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(*I))
FD = IFD->getAnonField();
if (FD && FD->hasInClassInitializer())
return FD->getLocation();
}
llvm_unreachable("couldn't find in-class initializer");
}
static void checkDuplicateDefaultInit(Sema &S, CXXRecordDecl *Parent,
SourceLocation DefaultInitLoc) {
if (!Parent->isUnion() || !Parent->hasInClassInitializer())
return;
S.Diag(DefaultInitLoc, diag::err_multiple_mem_union_initialization);
S.Diag(findDefaultInitializer(Parent), diag::note_previous_initializer) << 0;
}
static void checkDuplicateDefaultInit(Sema &S, CXXRecordDecl *Parent,
CXXRecordDecl *AnonUnion) {
if (!Parent->isUnion() || !Parent->hasInClassInitializer())
return;
checkDuplicateDefaultInit(S, Parent, findDefaultInitializer(AnonUnion));
}
Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
AccessSpecifier AS,
RecordDecl *Record,
const PrintingPolicy &Policy) {
DeclContext *Owner = Record->getDeclContext();
if (Record->isUnion() && !getLangOpts().CPlusPlus && !getLangOpts().C11)
Diag(Record->getLocation(), diag::ext_anonymous_union);
else if (!Record->isUnion() && getLangOpts().CPlusPlus)
Diag(Record->getLocation(), diag::ext_gnu_anonymous_struct);
else if (!Record->isUnion() && !getLangOpts().C11)
Diag(Record->getLocation(), diag::ext_c11_anonymous_struct);
bool Invalid = false;
if (getLangOpts().CPlusPlus) {
const char* PrevSpec = 0;
unsigned DiagID;
if (Record->isUnion()) {
if (DS.getStorageClassSpec() != DeclSpec::SCS_static &&
(isa<TranslationUnitDecl>(Owner) ||
(isa<NamespaceDecl>(Owner) &&
cast<NamespaceDecl>(Owner)->getDeclName()))) {
Diag(Record->getLocation(), diag::err_anonymous_union_not_static)
<< FixItHint::CreateInsertion(Record->getLocation(), "static ");
DS.SetStorageClassSpec(*this, DeclSpec::SCS_static, SourceLocation(),
PrevSpec, DiagID, Policy);
}
else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified &&
isa<RecordDecl>(Owner)) {
Diag(DS.getStorageClassSpecLoc(),
diag::err_anonymous_union_with_storage_spec)
<< FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
DS.SetStorageClassSpec(*this, DeclSpec::SCS_unspecified,
SourceLocation(),
PrevSpec, DiagID, Context.getPrintingPolicy());
}
}
if (DS.getTypeQualifiers()) {
if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
Diag(DS.getConstSpecLoc(), diag::ext_anonymous_struct_union_qualified)
<< Record->isUnion() << "const"
<< FixItHint::CreateRemoval(DS.getConstSpecLoc());
if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
Diag(DS.getVolatileSpecLoc(),
diag::ext_anonymous_struct_union_qualified)
<< Record->isUnion() << "volatile"
<< FixItHint::CreateRemoval(DS.getVolatileSpecLoc());
if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
Diag(DS.getRestrictSpecLoc(),
diag::ext_anonymous_struct_union_qualified)
<< Record->isUnion() << "restrict"
<< FixItHint::CreateRemoval(DS.getRestrictSpecLoc());
if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
Diag(DS.getAtomicSpecLoc(),
diag::ext_anonymous_struct_union_qualified)
<< Record->isUnion() << "_Atomic"
<< FixItHint::CreateRemoval(DS.getAtomicSpecLoc());
DS.ClearTypeQualifiers();
}
for (DeclContext::decl_iterator Mem = Record->decls_begin(),
MemEnd = Record->decls_end();
Mem != MemEnd; ++Mem) {
if (FieldDecl *FD = dyn_cast<FieldDecl>(*Mem)) {
assert(FD->getAccess() != AS_none);
if (FD->getAccess() != AS_public) {
Diag(FD->getLocation(), diag::err_anonymous_record_nonpublic_member)
<< (int)Record->isUnion() << (int)(FD->getAccess() == AS_protected);
Invalid = true;
}
if (CheckNontrivialField(FD))
Invalid = true;
} else if ((*Mem)->isImplicit()) {
} else if (isa<TagDecl>(*Mem) && (*Mem)->getDeclContext() != Record) {
} else if (RecordDecl *MemRecord = dyn_cast<RecordDecl>(*Mem)) {
if (!MemRecord->isAnonymousStructOrUnion() &&
MemRecord->getDeclName()) {
if (getLangOpts().MicrosoftExt)
Diag(MemRecord->getLocation(), diag::ext_anonymous_record_with_type)
<< (int)Record->isUnion();
else {
Diag(MemRecord->getLocation(), diag::err_anonymous_record_with_type)
<< (int)Record->isUnion();
Invalid = true;
}
} else {
Diag(MemRecord->getLocation(),
diag::ext_anonymous_record_with_anonymous_type)
<< (int)Record->isUnion();
}
} else if (isa<AccessSpecDecl>(*Mem)) {
} else {
unsigned DK = diag::err_anonymous_record_bad_member;
if (isa<TypeDecl>(*Mem))
DK = diag::err_anonymous_record_with_type;
else if (isa<FunctionDecl>(*Mem))
DK = diag::err_anonymous_record_with_function;
else if (isa<VarDecl>(*Mem))
DK = diag::err_anonymous_record_with_static;
if (getLangOpts().MicrosoftExt &&
DK == diag::err_anonymous_record_with_type)
Diag((*Mem)->getLocation(), diag::ext_anonymous_record_with_type)
<< (int)Record->isUnion();
else {
Diag((*Mem)->getLocation(), DK)
<< (int)Record->isUnion();
Invalid = true;
}
}
}
if (cast<CXXRecordDecl>(Record)->hasInClassInitializer() &&
Owner->isRecord())
checkDuplicateDefaultInit(*this, cast<CXXRecordDecl>(Owner),
cast<CXXRecordDecl>(Record));
}
if (!Record->isUnion() && !Owner->isRecord()) {
Diag(Record->getLocation(), diag::err_anonymous_struct_not_member)
<< (int)getLangOpts().CPlusPlus;
Invalid = true;
}
Declarator Dc(DS, Declarator::MemberContext);
TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
assert(TInfo && "couldn't build declarator info for anonymous struct/union");
NamedDecl *Anon = 0;
if (RecordDecl *OwningClass = dyn_cast<RecordDecl>(Owner)) {
Anon = FieldDecl::Create(Context, OwningClass,
DS.getLocStart(),
Record->getLocation(),
0,
Context.getTypeDeclType(Record),
TInfo,
0, false,
ICIS_NoInit);
Anon->setAccess(AS);
if (getLangOpts().CPlusPlus)
FieldCollector->Add(cast<FieldDecl>(Anon));
} else {
DeclSpec::SCS SCSpec = DS.getStorageClassSpec();
VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(DS);
if (SCSpec == DeclSpec::SCS_mutable) {
Diag(Record->getLocation(), diag::err_mutable_nonmember);
Invalid = true;
SC = SC_None;
}
Anon = VarDecl::Create(Context, Owner,
DS.getLocStart(),
Record->getLocation(), 0,
Context.getTypeDeclType(Record),
TInfo, SC);
ActOnUninitializedDecl(Anon, false);
}
Anon->setImplicit();
Record->setAnonymousStructOrUnion(true);
Owner->addDecl(Anon);
SmallVector<NamedDecl*, 2> Chain;
Chain.push_back(Anon);
if (InjectAnonymousStructOrUnionMembers(*this, S, Owner, Record, AS,
Chain, false))
Invalid = true;
if (Invalid)
Anon->setInvalidDecl();
return Anon;
}
Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
RecordDecl *Record) {
if (!Record)
Record = DS.getRepAsType().get()->getAsStructureType()->getDecl();
Declarator Dc(DS, Declarator::TypeNameContext);
TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
assert(TInfo && "couldn't build declarator info for anonymous struct");
NamedDecl* Anon = FieldDecl::Create(Context,
cast<RecordDecl>(CurContext),
DS.getLocStart(),
DS.getLocStart(),
0,
Context.getTypeDeclType(Record),
TInfo,
0, false,
ICIS_NoInit);
Anon->setImplicit();
CurContext->addDecl(Anon);
SmallVector<NamedDecl*, 2> Chain;
Chain.push_back(Anon);
RecordDecl *RecordDef = Record->getDefinition();
if (!RecordDef || InjectAnonymousStructOrUnionMembers(*this, S, CurContext,
RecordDef, AS_none,
Chain, true))
Anon->setInvalidDecl();
return Anon;
}
DeclarationNameInfo Sema::GetNameForDeclarator(Declarator &D) {
return GetNameFromUnqualifiedId(D.getName());
}
DeclarationNameInfo
Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
DeclarationNameInfo NameInfo;
NameInfo.setLoc(Name.StartLocation);
switch (Name.getKind()) {
case UnqualifiedId::IK_ImplicitSelfParam:
case UnqualifiedId::IK_Identifier:
NameInfo.setName(Name.Identifier);
NameInfo.setLoc(Name.StartLocation);
return NameInfo;
case UnqualifiedId::IK_OperatorFunctionId:
NameInfo.setName(Context.DeclarationNames.getCXXOperatorName(
Name.OperatorFunctionId.Operator));
NameInfo.setLoc(Name.StartLocation);
NameInfo.getInfo().CXXOperatorName.BeginOpNameLoc
= Name.OperatorFunctionId.SymbolLocations[0];
NameInfo.getInfo().CXXOperatorName.EndOpNameLoc
= Name.EndLocation.getRawEncoding();
return NameInfo;
case UnqualifiedId::IK_LiteralOperatorId:
NameInfo.setName(Context.DeclarationNames.getCXXLiteralOperatorName(
Name.Identifier));
NameInfo.setLoc(Name.StartLocation);
NameInfo.setCXXLiteralOperatorNameLoc(Name.EndLocation);
return NameInfo;
case UnqualifiedId::IK_ConversionFunctionId: {
TypeSourceInfo *TInfo;
QualType Ty = GetTypeFromParser(Name.ConversionFunctionId, &TInfo);
if (Ty.isNull())
return DeclarationNameInfo();
NameInfo.setName(Context.DeclarationNames.getCXXConversionFunctionName(
Context.getCanonicalType(Ty)));
NameInfo.setLoc(Name.StartLocation);
NameInfo.setNamedTypeInfo(TInfo);
return NameInfo;
}
case UnqualifiedId::IK_ConstructorName: {
TypeSourceInfo *TInfo;
QualType Ty = GetTypeFromParser(Name.ConstructorName, &TInfo);
if (Ty.isNull())
return DeclarationNameInfo();
NameInfo.setName(Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(Ty)));
NameInfo.setLoc(Name.StartLocation);
NameInfo.setNamedTypeInfo(TInfo);
return NameInfo;
}
case UnqualifiedId::IK_ConstructorTemplateId: {
CXXRecordDecl *CurClass = dyn_cast<CXXRecordDecl>(CurContext);
if (!CurClass || CurClass->getIdentifier() != Name.TemplateId->Name)
return DeclarationNameInfo();
QualType CurClassType = Context.getTypeDeclType(CurClass);
NameInfo.setName(Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(CurClassType)));
NameInfo.setLoc(Name.StartLocation);
NameInfo.setNamedTypeInfo(0);
return NameInfo;
}
case UnqualifiedId::IK_DestructorName: {
TypeSourceInfo *TInfo;
QualType Ty = GetTypeFromParser(Name.DestructorName, &TInfo);
if (Ty.isNull())
return DeclarationNameInfo();
NameInfo.setName(Context.DeclarationNames.getCXXDestructorName(
Context.getCanonicalType(Ty)));
NameInfo.setLoc(Name.StartLocation);
NameInfo.setNamedTypeInfo(TInfo);
return NameInfo;
}
case UnqualifiedId::IK_TemplateId: {
TemplateName TName = Name.TemplateId->Template.get();
SourceLocation TNameLoc = Name.TemplateId->TemplateNameLoc;
return Context.getNameForTemplate(TName, TNameLoc);
}
}
llvm_unreachable("Unknown name kind");
}
static QualType getCoreType(QualType Ty) {
do {
if (Ty->isPointerType() || Ty->isReferenceType())
Ty = Ty->getPointeeType();
else if (Ty->isArrayType())
Ty = Ty->castAsArrayTypeUnsafe()->getElementType();
else
return Ty.withoutLocalFastQualifiers();
} while (true);
}
static bool hasSimilarParameters(ASTContext &Context,
FunctionDecl *Declaration,
FunctionDecl *Definition,
SmallVectorImpl<unsigned> &Params) {
Params.clear();
if (Declaration->param_size() != Definition->param_size())
return false;
for (unsigned Idx = 0; Idx < Declaration->param_size(); ++Idx) {
QualType DeclParamTy = Declaration->getParamDecl(Idx)->getType();
QualType DefParamTy = Definition->getParamDecl(Idx)->getType();
if (Context.hasSameType(DefParamTy, DeclParamTy))
continue;
QualType DeclParamBaseTy = getCoreType(DeclParamTy);
QualType DefParamBaseTy = getCoreType(DefParamTy);
const IdentifierInfo *DeclTyName = DeclParamBaseTy.getBaseTypeIdentifier();
const IdentifierInfo *DefTyName = DefParamBaseTy.getBaseTypeIdentifier();
if (Context.hasSameUnqualifiedType(DeclParamBaseTy, DefParamBaseTy) ||
(DeclTyName && DeclTyName == DefTyName))
Params.push_back(Idx);
else return false;
}
return true;
}
static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
DeclarationName Name) {
DeclSpec &DS = D.getMutableDeclSpec();
switch (DS.getTypeSpecType()) {
case DeclSpec::TST_typename:
case DeclSpec::TST_typeofType:
case DeclSpec::TST_underlyingType:
case DeclSpec::TST_atomic: {
TypeSourceInfo *TSI = 0;
QualType T = S.GetTypeFromParser(DS.getRepAsType(), &TSI);
if (T.isNull() || !T->isDependentType()) break;
if (!TSI)
TSI = S.Context.getTrivialTypeSourceInfo(T, DS.getTypeSpecTypeLoc());
TSI = S.RebuildTypeInCurrentInstantiation(TSI, D.getIdentifierLoc(), Name);
if (!TSI) return true;
ParsedType LocType = S.CreateParsedType(TSI->getType(), TSI);
DS.UpdateTypeRep(LocType);
break;
}
case DeclSpec::TST_decltype:
case DeclSpec::TST_typeofExpr: {
Expr *E = DS.getRepAsExpr();
ExprResult Result = S.RebuildExprInCurrentInstantiation(E);
if (Result.isInvalid()) return true;
DS.UpdateExprRep(Result.get());
break;
}
default:
break;
}
for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) {
DeclaratorChunk &Chunk = D.getTypeObject(I);
if (Chunk.Kind != DeclaratorChunk::MemberPointer)
continue;
CXXScopeSpec &SS = Chunk.Mem.Scope();
if (S.RebuildNestedNameSpecifierInCurrentInstantiation(SS))
return true;
}
return false;
}
Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) {
D.setFunctionDefinitionKind(FDK_Declaration);
Decl *Dcl = HandleDeclarator(S, D, MultiTemplateParamsArg());
if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer() &&
Dcl && Dcl->getDeclContext()->isFileContext())
Dcl->setTopLevelDeclInObjCContainer();
return Dcl;
}
bool Sema::DiagnoseClassNameShadow(DeclContext *DC,
DeclarationNameInfo NameInfo) {
DeclarationName Name = NameInfo.getName();
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
if (Record->getIdentifier() && Record->getDeclName() == Name) {
Diag(NameInfo.getLoc(), diag::err_member_name_of_class) << Name;
return true;
}
return false;
}
bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
DeclarationName Name,
SourceLocation Loc) {
DeclContext *Cur = CurContext;
while (isa<LinkageSpecDecl>(Cur) || isa<CapturedDecl>(Cur))
Cur = Cur->getParent();
if (Cur->Equals(DC)) {
if (Cur->isRecord()) {
Diag(Loc, LangOpts.MicrosoftExt ? diag::warn_member_extra_qualification
: diag::err_member_extra_qualification)
<< Name << FixItHint::CreateRemoval(SS.getRange());
SS.clear();
} else {
Diag(Loc, diag::warn_namespace_member_extra_qualification) << Name;
}
return false;
}
if (!Cur->Encloses(DC)) {
if (Cur->isRecord())
Diag(Loc, diag::err_member_qualification)
<< Name << SS.getRange();
else if (isa<TranslationUnitDecl>(DC))
Diag(Loc, diag::err_invalid_declarator_global_scope)
<< Name << SS.getRange();
else if (isa<FunctionDecl>(Cur))
Diag(Loc, diag::err_invalid_declarator_in_function)
<< Name << SS.getRange();
else if (isa<BlockDecl>(Cur))
Diag(Loc, diag::err_invalid_declarator_in_block)
<< Name << SS.getRange();
else
Diag(Loc, diag::err_invalid_declarator_scope)
<< Name << cast<NamedDecl>(Cur) << cast<NamedDecl>(DC) << SS.getRange();
return true;
}
if (Cur->isRecord()) {
Diag(Loc, diag::err_member_qualification)
<< Name << SS.getRange();
SS.clear();
if ((Name.getNameKind() == DeclarationName::CXXConstructorName ||
Name.getNameKind() == DeclarationName::CXXDestructorName) &&
!Context.hasSameType(Name.getCXXNameType(),
Context.getTypeDeclType(cast<CXXRecordDecl>(Cur))))
return true;
return false;
}
NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data());
while (SpecLoc.getPrefix())
SpecLoc = SpecLoc.getPrefix();
if (dyn_cast_or_null<DecltypeType>(
SpecLoc.getNestedNameSpecifier()->getAsType()))
Diag(Loc, diag::err_decltype_in_declarator)
<< SpecLoc.getTypeLoc().getSourceRange();
return false;
}
NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
MultiTemplateParamsArg TemplateParamLists) {
DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
DeclarationName Name = NameInfo.getName();
if (!Name) {
if (!D.isInvalidType()) Diag(D.getDeclSpec().getLocStart(),
diag::err_declarator_need_ident)
<< D.getDeclSpec().getSourceRange() << D.getSourceRange();
return 0;
} else if (DiagnoseUnexpandedParameterPack(NameInfo, UPPC_DeclarationType))
return 0;
while ((S->getFlags() & Scope::DeclScope) == 0 ||
(S->getFlags() & Scope::TemplateParamScope) != 0)
S = S->getParent();
DeclContext *DC = CurContext;
if (D.getCXXScopeSpec().isInvalid())
D.setInvalidType();
else if (D.getCXXScopeSpec().isSet()) {
if (DiagnoseUnexpandedParameterPack(D.getCXXScopeSpec(),
UPPC_DeclarationQualifier))
return 0;
bool EnteringContext = !D.getDeclSpec().isFriendSpecified();
DC = computeDeclContext(D.getCXXScopeSpec(), EnteringContext);
if (!DC || isa<EnumDecl>(DC)) {
Diag(D.getIdentifierLoc(),
diag::err_template_qualified_declarator_no_match)
<< D.getCXXScopeSpec().getScopeRep()
<< D.getCXXScopeSpec().getRange();
return 0;
}
bool IsDependentContext = DC->isDependentContext();
if (!IsDependentContext &&
RequireCompleteDeclContext(D.getCXXScopeSpec(), DC))
return 0;
if (isa<CXXRecordDecl>(DC) && !cast<CXXRecordDecl>(DC)->hasDefinition()) {
Diag(D.getIdentifierLoc(),
diag::err_member_def_undefined_record)
<< Name << DC << D.getCXXScopeSpec().getRange();
D.setInvalidType();
} else if (!D.getDeclSpec().isFriendSpecified()) {
if (diagnoseQualifiedDeclaration(D.getCXXScopeSpec(), DC,
Name, D.getIdentifierLoc())) {
if (DC->isRecord())
return 0;
D.setInvalidType();
}
}
if (EnteringContext && IsDependentContext &&
TemplateParamLists.size() != 0) {
ContextRAII SavedContext(*this, DC);
if (RebuildDeclaratorInCurrentInstantiation(*this, D, Name))
D.setInvalidType();
}
}
if (DiagnoseClassNameShadow(DC, NameInfo))
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
return 0;
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType R = TInfo->getType();
if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
UPPC_DeclarationType))
D.setInvalidType();
LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
ForRedeclaration);
if (!D.getCXXScopeSpec().isSet()) {
bool IsLinkageLookup = false;
bool CreateBuiltins = false;
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
;
else if (CurContext->isFunctionOrMethod() &&
(D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern ||
R->isFunctionType())) {
IsLinkageLookup = true;
CreateBuiltins =
CurContext->getEnclosingNamespaceContext()->isTranslationUnit();
} else if (CurContext->getRedeclContext()->isTranslationUnit() &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
CreateBuiltins = true;
if (IsLinkageLookup)
Previous.clear(LookupRedeclarationWithLinkage);
LookupName(Previous, S, CreateBuiltins);
} else { LookupQualifiedName(Previous, DC);
RemoveUsingDecls(Previous);
}
if (Previous.isSingleResult() &&
Previous.getFoundDecl()->isTemplateParameter()) {
if (!D.isInvalidType())
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
Previous.getFoundDecl());
Previous.clear();
}
if (Previous.isSingleTagDecl() &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef)
Previous.clear();
if (getLangOpts().CPlusPlus)
CheckExtraCXXDefaultArguments(D);
NamedDecl *New;
bool AddToScope = true;
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
if (TemplateParamLists.size()) {
Diag(D.getIdentifierLoc(), diag::err_template_typedef);
return 0;
}
New = ActOnTypedefDeclarator(S, D, DC, TInfo, Previous);
} else if (R->isFunctionType()) {
New = ActOnFunctionDeclarator(S, D, DC, TInfo, Previous,
TemplateParamLists,
AddToScope);
} else {
New = ActOnVariableDeclarator(S, D, DC, TInfo, Previous, TemplateParamLists,
AddToScope);
}
if (New == 0)
return 0;
if (New->getDeclName() && AddToScope &&
!(D.isRedeclaration() && New->isInvalidDecl())) {
bool AddToContext = !D.isRedeclaration() || !New->isLocalExternDecl();
PushOnScopeChains(New, S, AddToContext);
if (!AddToContext)
CurContext->addHiddenDecl(New);
}
return New;
}
static QualType TryToFixInvalidVariablyModifiedType(QualType T,
ASTContext &Context,
bool &SizeIsNegative,
llvm::APSInt &Oversized) {
SizeIsNegative = false;
Oversized = 0;
if (T->isDependentType())
return QualType();
QualifierCollector Qs;
const Type *Ty = Qs.strip(T);
if (const PointerType* PTy = dyn_cast<PointerType>(Ty)) {
QualType Pointee = PTy->getPointeeType();
QualType FixedType =
TryToFixInvalidVariablyModifiedType(Pointee, Context, SizeIsNegative,
Oversized);
if (FixedType.isNull()) return FixedType;
FixedType = Context.getPointerType(FixedType);
return Qs.apply(Context, FixedType);
}
if (const ParenType* PTy = dyn_cast<ParenType>(Ty)) {
QualType Inner = PTy->getInnerType();
QualType FixedType =
TryToFixInvalidVariablyModifiedType(Inner, Context, SizeIsNegative,
Oversized);
if (FixedType.isNull()) return FixedType;
FixedType = Context.getParenType(FixedType);
return Qs.apply(Context, FixedType);
}
const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T);
if (!VLATy)
return QualType();
if (VLATy->getElementType()->isVariablyModifiedType())
return QualType();
llvm::APSInt Res;
if (!VLATy->getSizeExpr() ||
!VLATy->getSizeExpr()->EvaluateAsInt(Res, Context))
return QualType();
if (Res.isSigned() && Res.isNegative()) {
SizeIsNegative = true;
return QualType();
}
unsigned ActiveSizeBits
= ConstantArrayType::getNumAddressingBits(Context, VLATy->getElementType(),
Res);
if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
Oversized = Res;
return QualType();
}
return Context.getConstantArrayType(VLATy->getElementType(),
Res, ArrayType::Normal, 0);
}
static void
FixInvalidVariablyModifiedTypeLoc(TypeLoc SrcTL, TypeLoc DstTL) {
if (PointerTypeLoc SrcPTL = SrcTL.getAs<PointerTypeLoc>()) {
PointerTypeLoc DstPTL = DstTL.castAs<PointerTypeLoc>();
FixInvalidVariablyModifiedTypeLoc(SrcPTL.getPointeeLoc(),
DstPTL.getPointeeLoc());
DstPTL.setStarLoc(SrcPTL.getStarLoc());
return;
}
if (ParenTypeLoc SrcPTL = SrcTL.getAs<ParenTypeLoc>()) {
ParenTypeLoc DstPTL = DstTL.castAs<ParenTypeLoc>();
FixInvalidVariablyModifiedTypeLoc(SrcPTL.getInnerLoc(),
DstPTL.getInnerLoc());
DstPTL.setLParenLoc(SrcPTL.getLParenLoc());
DstPTL.setRParenLoc(SrcPTL.getRParenLoc());
return;
}
ArrayTypeLoc SrcATL = SrcTL.castAs<ArrayTypeLoc>();
ArrayTypeLoc DstATL = DstTL.castAs<ArrayTypeLoc>();
TypeLoc SrcElemTL = SrcATL.getElementLoc();
TypeLoc DstElemTL = DstATL.getElementLoc();
DstElemTL.initializeFullCopy(SrcElemTL);
DstATL.setLBracketLoc(SrcATL.getLBracketLoc());
DstATL.setSizeExpr(SrcATL.getSizeExpr());
DstATL.setRBracketLoc(SrcATL.getRBracketLoc());
}
static TypeSourceInfo*
TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo,
ASTContext &Context,
bool &SizeIsNegative,
llvm::APSInt &Oversized) {
QualType FixedTy
= TryToFixInvalidVariablyModifiedType(TInfo->getType(), Context,
SizeIsNegative, Oversized);
if (FixedTy.isNull())
return 0;
TypeSourceInfo *FixedTInfo = Context.getTrivialTypeSourceInfo(FixedTy);
FixInvalidVariablyModifiedTypeLoc(TInfo->getTypeLoc(),
FixedTInfo->getTypeLoc());
return FixedTInfo;
}
void
Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S) {
if (!getLangOpts().CPlusPlus &&
ND->getLexicalDeclContext()->getRedeclContext()->isTranslationUnit())
return;
LocallyScopedExternCDecls[ND->getDeclName()] = ND;
}
NamedDecl *Sema::findLocallyScopedExternCDecl(DeclarationName Name) {
if (ExternalSource) {
SmallVector<NamedDecl *, 4> Decls;
ExternalSource->ReadLocallyScopedExternCDecls(Decls);
for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
= LocallyScopedExternCDecls.find(Decls[I]->getDeclName());
if (Pos == LocallyScopedExternCDecls.end())
LocallyScopedExternCDecls[Decls[I]->getDeclName()] = Decls[I];
}
}
NamedDecl *D = LocallyScopedExternCDecls.lookup(Name);
return D ? D->getMostRecentDecl() : 0;
}
void Sema::DiagnoseFunctionSpecifiers(const DeclSpec &DS) {
if (DS.isInlineSpecified())
Diag(DS.getInlineSpecLoc(),
diag::err_inline_non_function);
if (DS.isVirtualSpecified())
Diag(DS.getVirtualSpecLoc(),
diag::err_virtual_non_function);
if (DS.isExplicitSpecified())
Diag(DS.getExplicitSpecLoc(),
diag::err_explicit_non_function);
if (DS.isNoreturnSpecified())
Diag(DS.getNoreturnSpecLoc(),
diag::err_noreturn_non_function);
}
NamedDecl*
Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
TypeSourceInfo *TInfo, LookupResult &Previous) {
if (D.getCXXScopeSpec().isSet()) {
Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator)
<< D.getCXXScopeSpec().getRange();
D.setInvalidType();
DC = CurContext;
Previous.clear();
}
DiagnoseFunctionSpecifiers(D.getDeclSpec());
if (D.getDeclSpec().isConstexprSpecified())
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
<< 1;
if (D.getName().Kind != UnqualifiedId::IK_Identifier) {
Diag(D.getName().StartLocation, diag::err_typedef_not_identifier)
<< D.getName().getSourceRange();
return 0;
}
TypedefDecl *NewTD = ParseTypedefDecl(S, D, TInfo->getType(), TInfo);
if (!NewTD) return 0;
ProcessDeclAttributes(S, NewTD, D);
CheckTypedefForVariablyModifiedType(S, NewTD);
bool Redeclaration = D.isRedeclaration();
NamedDecl *ND = ActOnTypedefNameDecl(S, DC, NewTD, Previous, Redeclaration);
D.setRedeclaration(Redeclaration);
return ND;
}
void
Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) {
TypeSourceInfo *TInfo = NewTD->getTypeSourceInfo();
QualType T = TInfo->getType();
if (T->isVariablyModifiedType()) {
getCurFunction()->setHasBranchProtectedScope();
if (S->getFnParent() == 0) {
bool SizeIsNegative;
llvm::APSInt Oversized;
TypeSourceInfo *FixedTInfo =
TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context,
SizeIsNegative,
Oversized);
if (FixedTInfo) {
Diag(NewTD->getLocation(), diag::warn_illegal_constant_array_size);
NewTD->setTypeSourceInfo(FixedTInfo);
} else {
if (SizeIsNegative)
Diag(NewTD->getLocation(), diag::err_typecheck_negative_array_size);
else if (T->isVariableArrayType())
Diag(NewTD->getLocation(), diag::err_vla_decl_in_file_scope);
else if (Oversized.getBoolValue())
Diag(NewTD->getLocation(), diag::err_array_too_large)
<< Oversized.toString(10);
else
Diag(NewTD->getLocation(), diag::err_vm_decl_in_file_scope);
NewTD->setInvalidDecl();
}
}
}
}
NamedDecl*
Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD,
LookupResult &Previous, bool &Redeclaration) {
FilterLookupForScope(Previous, DC, S, false,
false);
filterNonConflictingPreviousDecls(Context, NewTD, Previous);
if (!Previous.empty()) {
Redeclaration = true;
MergeTypedefNameDecl(NewTD, Previous);
}
if (IdentifierInfo *II = NewTD->getIdentifier())
if (!NewTD->isInvalidDecl() &&
NewTD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
if (II->isStr("FILE"))
Context.setFILEDecl(NewTD);
else if (II->isStr("jmp_buf"))
Context.setjmp_bufDecl(NewTD);
else if (II->isStr("sigjmp_buf"))
Context.setsigjmp_bufDecl(NewTD);
else if (II->isStr("ucontext_t"))
Context.setucontext_tDecl(NewTD);
}
return NewTD;
}
static bool
isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC,
ASTContext &Context) {
if (!PrevDecl)
return false;
if (!PrevDecl->hasLinkage())
return false;
if (Context.getLangOpts().CPlusPlus) {
DeclContext *OuterContext = DC->getRedeclContext();
if (!OuterContext->isFunctionOrMethod())
return false;
DeclContext *PrevOuterContext = PrevDecl->getDeclContext();
if (PrevOuterContext->isRecord())
return false;
OuterContext = OuterContext->getEnclosingNamespaceContext();
PrevOuterContext = PrevOuterContext->getEnclosingNamespaceContext();
if (!OuterContext->Equals(PrevOuterContext))
return false;
}
return true;
}
static void SetNestedNameSpecifier(DeclaratorDecl *DD, Declarator &D) {
CXXScopeSpec &SS = D.getCXXScopeSpec();
if (!SS.isSet()) return;
DD->setQualifierInfo(SS.getWithLocInContext(DD->getASTContext()));
}
bool Sema::inferObjCARCLifetime(ValueDecl *decl) {
QualType type = decl->getType();
Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime();
if (lifetime == Qualifiers::OCL_Autoreleasing) {
unsigned kind = -1U;
if (VarDecl *var = dyn_cast<VarDecl>(decl)) {
if (var->hasAttr<BlocksAttr>())
kind = 0; else if (!var->hasLocalStorage())
kind = 1; } else if (isa<ObjCIvarDecl>(decl)) {
kind = 3; } else if (isa<FieldDecl>(decl)) {
kind = 2; }
if (kind != -1U) {
Diag(decl->getLocation(), diag::err_arc_autoreleasing_var)
<< kind;
}
} else if (lifetime == Qualifiers::OCL_None) {
if (!type->isObjCLifetimeType())
return false;
lifetime = type->getObjCARCImplicitLifetime();
type = Context.getLifetimeQualifiedType(type, lifetime);
decl->setType(type);
}
if (VarDecl *var = dyn_cast<VarDecl>(decl)) {
if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone &&
var->getTLSKind()) {
Diag(var->getLocation(), diag::err_arc_thread_ownership)
<< var->getType();
return true;
}
}
return false;
}
static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
assert(S.ParsingInitForAutoVars.count(&ND) == 0);
if (WeakAttr *Attr = ND.getAttr<WeakAttr>()) {
if (!ND.isExternallyVisible()) {
S.Diag(Attr->getLocation(), diag::err_attribute_weak_static);
ND.dropAttr<WeakAttr>();
}
}
if (WeakRefAttr *Attr = ND.getAttr<WeakRefAttr>()) {
if (ND.isExternallyVisible()) {
S.Diag(Attr->getLocation(), diag::err_attribute_weakref_not_static);
ND.dropAttr<WeakRefAttr>();
}
}
if (SelectAnyAttr *Attr = ND.getAttr<SelectAnyAttr>()) {
if (isa<FunctionDecl>(ND) || !ND.isExternallyVisible()) {
S.Diag(Attr->getLocation(), diag::err_attribute_selectany_non_extern_data);
ND.dropAttr<SelectAnyAttr>();
}
}
}
static bool isFunctionDefinitionDiscarded(Sema &S, FunctionDecl *FD) {
if (!FD->isInlined()) return false;
if (S.getLangOpts().CPlusPlus && !FD->hasAttr<GNUInlineAttr>())
return false;
#ifndef NDEBUG
FD->setLazyBody(1);
#endif
bool isC99Inline = (S.Context.GetGVALinkageForFunction(FD) == GVA_C99Inline);
#ifndef NDEBUG
FD->setLazyBody(0);
#endif
return isC99Inline;
}
template<typename T>
static bool isIncompleteDeclExternC(Sema &S, const T *D) {
if (S.getLangOpts().CPlusPlus) {
if (!D->isInExternCContext() || D->template hasAttr<OverloadableAttr>())
return false;
}
return D->isExternC();
}
static bool shouldConsiderLinkage(const VarDecl *VD) {
const DeclContext *DC = VD->getDeclContext()->getRedeclContext();
if (DC->isFunctionOrMethod())
return VD->hasExternalStorage();
if (DC->isFileContext())
return true;
if (DC->isRecord())
return false;
llvm_unreachable("Unexpected context");
}
static bool shouldConsiderLinkage(const FunctionDecl *FD) {
const DeclContext *DC = FD->getDeclContext()->getRedeclContext();
if (DC->isFileContext() || DC->isFunctionOrMethod())
return true;
if (DC->isRecord())
return false;
llvm_unreachable("Unexpected context");
}
bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) {
if (!DC->isFunctionOrMethod())
return false;
if (DC->isDependentContext())
return true;
while (!DC->isFileContext() && !isa<LinkageSpecDecl>(DC))
DC = DC->getParent();
return true;
}
NamedDecl *
Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
TypeSourceInfo *TInfo, LookupResult &Previous,
MultiTemplateParamsArg TemplateParamLists,
bool &AddToScope) {
QualType R = TInfo->getType();
DeclarationName Name = GetNameForDeclarator(D).getName();
DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
VarDecl::StorageClass SC =
StorageClassSpecToVarDeclStorageClass(D.getDeclSpec());
DeclContext *OriginalDC = DC;
bool IsLocalExternDecl = SC == SC_Extern &&
adjustContextForLocalExternDecl(DC);
if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16) {
if (Context.getBaseElementType(R)->isHalfType()) {
Diag(D.getIdentifierLoc(), diag::err_opencl_half_declaration) << R;
D.setInvalidType();
}
}
if (SCSpec == DeclSpec::SCS_mutable) {
Diag(D.getIdentifierLoc(), diag::err_mutable_nonmember);
D.setInvalidType();
SC = SC_None;
}
if (getLangOpts().CPlusPlus11 && SCSpec == DeclSpec::SCS_register &&
!D.getAsmLabel() && !getSourceManager().isInSystemMacro(
D.getDeclSpec().getStorageClassSpecLoc())) {
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::warn_deprecated_register)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
}
IdentifierInfo *II = Name.getAsIdentifierInfo();
if (!II) {
Diag(D.getIdentifierLoc(), diag::err_bad_variable_name)
<< Name;
return 0;
}
DiagnoseFunctionSpecifiers(D.getDeclSpec());
if (!DC->isRecord() && S->getFnParent() == 0) {
if (SC == SC_Auto || SC == SC_Register) {
if (SC == SC_Register && D.getAsmLabel())
Diag(D.getIdentifierLoc(), diag::err_unsupported_global_register);
else
Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope);
D.setInvalidType();
}
}
if (getLangOpts().OpenCL) {
if (R.getAddressSpace() == LangAS::opencl_local) {
SC = SC_OpenCLWorkGroupLocal;
}
if (R->isSamplerT() && (R.getAddressSpace() == LangAS::opencl_local ||
R.getAddressSpace() == LangAS::opencl_global)) {
Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace);
}
if (R->isEventT()) {
if (S->getParent() == 0) {
Diag(D.getLocStart(), diag::err_event_t_global_var);
D.setInvalidType();
}
if (R.getAddressSpace()) {
Diag(D.getLocStart(), diag::err_event_t_addr_space_qual);
D.setInvalidType();
}
}
}
bool IsExplicitSpecialization = false;
bool IsVariableTemplateSpecialization = false;
bool IsPartialSpecialization = false;
bool IsVariableTemplate = false;
VarDecl *NewVD = 0;
VarTemplateDecl *NewTemplate = 0;
TemplateParameterList *TemplateParams = 0;
if (!getLangOpts().CPlusPlus) {
NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
D.getIdentifierLoc(), II,
R, TInfo, SC);
if (D.isInvalidType())
NewVD->setInvalidDecl();
} else {
bool Invalid = false;
if (DC->isRecord() && !CurContext->isRecord()) {
switch (SC) {
case SC_None:
break;
case SC_Static:
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::err_static_out_of_line)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
break;
case SC_Auto:
case SC_Register:
case SC_Extern:
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::err_storage_class_for_static_member)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
break;
case SC_PrivateExtern:
llvm_unreachable("C storage class in c++!");
case SC_OpenCLWorkGroupLocal:
llvm_unreachable("OpenCL storage class in c++!");
}
}
if (SC == SC_Static && CurContext->isRecord()) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
if (RD->isLocalClass())
Diag(D.getIdentifierLoc(),
diag::err_static_data_member_not_allowed_in_local_class)
<< Name << RD->getDeclName();
if (RD->isUnion())
Diag(D.getIdentifierLoc(),
getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_static_data_member_in_union
: diag::ext_static_data_member_in_union) << Name;
else if (!RD->getDeclName())
Diag(D.getIdentifierLoc(),
diag::err_static_data_member_not_allowed_in_anon_struct)
<< Name << RD->isUnion();
}
}
TemplateParams = MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
D.getCXXScopeSpec(), TemplateParamLists,
false, IsExplicitSpecialization, Invalid);
if (D.getName().getKind() == UnqualifiedId::IK_TemplateId &&
!TemplateParams) {
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
<< FixItHint::CreateInsertion(D.getDeclSpec().getLocStart(),
"template<> ");
IsVariableTemplateSpecialization = true;
TemplateParams = TemplateParameterList::Create(Context, SourceLocation(),
SourceLocation(), 0, 0,
SourceLocation());
}
if (TemplateParams) {
if (!TemplateParams->size() &&
D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
Diag(TemplateParams->getTemplateLoc(),
diag::err_template_variable_noparams)
<< II
<< SourceRange(TemplateParams->getTemplateLoc(),
TemplateParams->getRAngleLoc());
TemplateParams = 0;
} else {
Diag(D.getIdentifierLoc(),
getLangOpts().CPlusPlus1y
? diag::warn_cxx11_compat_variable_template
: diag::ext_variable_template);
if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
IsVariableTemplateSpecialization = true;
IsPartialSpecialization = TemplateParams->size() > 0;
} else { IsVariableTemplate = true;
if (CheckTemplateDeclScope(S, TemplateParams))
return 0;
}
}
}
if (IsVariableTemplateSpecialization) {
SourceLocation TemplateKWLoc =
TemplateParamLists.size() > 0
? TemplateParamLists[0]->getTemplateLoc()
: SourceLocation();
DeclResult Res = ActOnVarTemplateSpecialization(
S, D, TInfo, TemplateKWLoc, TemplateParams, SC,
IsPartialSpecialization);
if (Res.isInvalid())
return 0;
NewVD = cast<VarDecl>(Res.get());
AddToScope = false;
} else
NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
D.getIdentifierLoc(), II, R, TInfo, SC);
if (IsVariableTemplate) {
NewTemplate =
VarTemplateDecl::Create(Context, DC, D.getIdentifierLoc(), Name,
TemplateParams, NewVD);
NewVD->setDescribedVarTemplate(NewTemplate);
}
if (D.getDeclSpec().containsPlaceholderType() && R->getContainedAutoType())
ParsingInitForAutoVars.insert(NewVD);
if (D.isInvalidType() || Invalid) {
NewVD->setInvalidDecl();
if (NewTemplate)
NewTemplate->setInvalidDecl();
}
SetNestedNameSpecifier(NewVD, D);
if (TemplateParams && TemplateParamLists.size() > 1 &&
(!IsVariableTemplateSpecialization || D.getCXXScopeSpec().isSet())) {
NewVD->setTemplateParameterListsInfo(
Context, TemplateParamLists.size() - 1, TemplateParamLists.data());
} else if (IsVariableTemplateSpecialization ||
(!TemplateParams && TemplateParamLists.size() > 0 &&
(D.getCXXScopeSpec().isSet()))) {
NewVD->setTemplateParameterListsInfo(Context,
TemplateParamLists.size(),
TemplateParamLists.data());
}
if (D.getDeclSpec().isConstexprSpecified())
NewVD->setConstexpr(true);
}
NewVD->setLexicalDeclContext(CurContext);
if (NewTemplate)
NewTemplate->setLexicalDeclContext(CurContext);
if (IsLocalExternDecl)
NewVD->setLocalExternDecl();
if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) {
if (NewVD->hasLocalStorage()) {
if (SCSpec == DeclSpec::SCS_unspecified &&
TSCS == DeclSpec::TSCS_thread_local &&
DC->isFunctionOrMethod())
NewVD->setTSCSpec(TSCS);
else
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_thread_non_global)
<< DeclSpec::getSpecifierName(TSCS);
} else if (!Context.getTargetInfo().isTLSSupported())
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_thread_unsupported);
else if (TSCS == DeclSpec::TSCS_thread_local &&
Context.getTargetInfo().getTriple().isOSDarwin())
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_thread_unsupported);
else
NewVD->setTSCSpec(TSCS);
}
if (SC == SC_Static && S->getFnParent() != 0 &&
!NewVD->getType().isConstQualified()) {
FunctionDecl *CurFD = getCurFunctionDecl();
if (CurFD && isFunctionDefinitionDiscarded(*this, CurFD)) {
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::warn_static_local_in_extern_inline);
MaybeSuggestAddingStaticToDecl(CurFD);
}
}
if (D.getDeclSpec().isModulePrivateSpecified()) {
if (IsVariableTemplateSpecialization)
Diag(NewVD->getLocation(), diag::err_module_private_specialization)
<< (IsPartialSpecialization ? 1 : 0)
<< FixItHint::CreateRemoval(
D.getDeclSpec().getModulePrivateSpecLoc());
else if (IsExplicitSpecialization)
Diag(NewVD->getLocation(), diag::err_module_private_specialization)
<< 2
<< FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
else if (NewVD->hasLocalStorage())
Diag(NewVD->getLocation(), diag::err_module_private_local)
<< 0 << NewVD->getDeclName()
<< SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
<< FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
else {
NewVD->setModulePrivate();
if (NewTemplate)
NewTemplate->setModulePrivate();
}
}
ProcessDeclAttributes(S, NewVD, D);
if (NewVD->hasAttrs())
CheckAlignasUnderalignment(NewVD);
if (getLangOpts().CUDA) {
if (SC == SC_None && S->getFnParent() != 0 &&
(NewVD->hasAttr<CUDASharedAttr>() ||
NewVD->hasAttr<CUDAConstantAttr>())) {
NewVD->setStorageClass(SC_Static);
}
}
if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewVD))
NewVD->setInvalidDecl();
if (Expr *E = (Expr*)D.getAsmLabel()) {
StringLiteral *SE = cast<StringLiteral>(E);
StringRef Label = SE->getString();
if (S->getFnParent() != 0) {
switch (SC) {
case SC_None:
case SC_Auto:
Diag(E->getExprLoc(), diag::warn_asm_label_on_auto_decl) << Label;
break;
case SC_Register:
if (!Context.getTargetInfo().isValidGCCRegisterName(Label))
Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
break;
case SC_Static:
case SC_Extern:
case SC_PrivateExtern:
case SC_OpenCLWorkGroupLocal:
break;
}
}
NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0),
Context, Label, 0));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
if (I != ExtnameUndeclaredIdentifiers.end()) {
NewVD->addAttr(I->second);
ExtnameUndeclaredIdentifiers.erase(I);
}
}
if (D.getCXXScopeSpec().isEmpty())
CheckShadow(S, NewVD, Previous);
FilterLookupForScope(Previous, OriginalDC, S, shouldConsiderLinkage(NewVD),
D.getCXXScopeSpec().isNotEmpty() ||
IsExplicitSpecialization ||
IsVariableTemplateSpecialization);
if (getLangOpts().CPlusPlus &&
NewVD->isLocalVarDecl() && NewVD->hasExternalStorage())
NewVD->setPreviousDeclInSameBlockScope(
Previous.isSingleResult() && !Previous.isShadowed() &&
isDeclInScope(Previous.getFoundDecl(), OriginalDC, S, false));
if (!getLangOpts().CPlusPlus) {
D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
} else {
if (IsExplicitSpecialization && !NewVD->isInvalidDecl() &&
CheckMemberSpecialization(NewVD, Previous))
NewVD->setInvalidDecl();
if (!Previous.empty()) {
if (Previous.isSingleResult() &&
isa<FieldDecl>(Previous.getFoundDecl()) &&
D.getCXXScopeSpec().isSet()) {
Diag(NewVD->getLocation(), diag::err_nonstatic_member_out_of_line)
<< D.getCXXScopeSpec().getRange();
Previous.clear();
NewVD->setInvalidDecl();
}
} else if (D.getCXXScopeSpec().isSet()) {
Diag(D.getIdentifierLoc(), diag::err_no_member)
<< Name << computeDeclContext(D.getCXXScopeSpec(), true)
<< D.getCXXScopeSpec().getRange();
NewVD->setInvalidDecl();
}
if (!IsVariableTemplateSpecialization)
D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
if (NewTemplate) {
VarTemplateDecl *PrevVarTemplate =
NewVD->getPreviousDecl()
? NewVD->getPreviousDecl()->getDescribedVarTemplate()
: 0;
if (CheckTemplateParameterList(
TemplateParams,
PrevVarTemplate ? PrevVarTemplate->getTemplateParameters()
: 0,
(D.getCXXScopeSpec().isSet() && DC && DC->isRecord() &&
DC->isDependentContext())
? TPC_ClassTemplateMember
: TPC_VarTemplate))
NewVD->setInvalidDecl();
if (PrevVarTemplate &&
PrevVarTemplate->getInstantiatedFromMemberTemplate())
PrevVarTemplate->setMemberSpecialization();
}
}
ProcessPragmaWeak(S, NewVD);
if (NewVD->isFirstDecl() && !NewVD->isInvalidDecl() &&
isIncompleteDeclExternC(*this, NewVD))
RegisterLocallyScopedExternCDecl(NewVD, S);
if (getLangOpts().CPlusPlus && NewVD->isStaticLocal()) {
Decl *ManglingContextDecl;
if (MangleNumberingContext *MCtx =
getCurrentMangleNumberContext(NewVD->getDeclContext(),
ManglingContextDecl)) {
Context.setManglingNumber(NewVD, MCtx->getManglingNumber(NewVD));
}
}
if (NewTemplate) {
if (NewVD->isInvalidDecl())
NewTemplate->setInvalidDecl();
ActOnDocumentableDecl(NewTemplate);
return NewTemplate;
}
return NewVD;
}
void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) {
if (Diags.getDiagnosticLevel(diag::warn_decl_shadow, R.getNameLoc()) ==
DiagnosticsEngine::Ignored)
return;
if (D->hasGlobalStorage())
return;
DeclContext *NewDC = D->getDeclContext();
if (R.getResultKind() != LookupResult::Found)
return;
NamedDecl* ShadowedDecl = R.getFoundDecl();
if (!isa<VarDecl>(ShadowedDecl) && !isa<FieldDecl>(ShadowedDecl))
return;
if (isa<FieldDecl>(ShadowedDecl))
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewDC))
if (MD->isStatic())
return;
if (VarDecl *shadowedVar = dyn_cast<VarDecl>(ShadowedDecl))
if (shadowedVar->isExternC()) {
for (VarDecl::redecl_iterator
I = shadowedVar->redecls_begin(), E = shadowedVar->redecls_end();
I != E; ++I)
if (I->isFileVarDecl()) {
ShadowedDecl = *I;
break;
}
}
DeclContext *OldDC = ShadowedDecl->getDeclContext();
if (NewDC && NewDC->isRecord()) {
if (!OldDC->isRecord())
return;
}
unsigned Kind;
if (isa<RecordDecl>(OldDC)) {
if (isa<FieldDecl>(ShadowedDecl))
Kind = 3; else
Kind = 2; } else if (OldDC->isFileContext())
Kind = 1; else
Kind = 0;
DeclarationName Name = R.getLookupName();
if (getSourceManager().isInSystemMacro(R.getNameLoc()))
return;
Diag(R.getNameLoc(), diag::warn_decl_shadow) << Name << Kind << OldDC;
Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration);
}
void Sema::CheckShadow(Scope *S, VarDecl *D) {
if (Diags.getDiagnosticLevel(diag::warn_decl_shadow, D->getLocation()) ==
DiagnosticsEngine::Ignored)
return;
LookupResult R(*this, D->getDeclName(), D->getLocation(),
Sema::LookupOrdinaryName, Sema::ForRedeclaration);
LookupName(R, S);
CheckShadow(S, D, R);
}
template<typename T>
static bool checkGlobalOrExternCConflict(
Sema &S, const T *ND, bool IsGlobal, LookupResult &Previous) {
assert(S.getLangOpts().CPlusPlus && "only C++ has extern \"C\"");
NamedDecl *Prev = S.findLocallyScopedExternCDecl(ND->getDeclName());
if (!Prev && IsGlobal && !isIncompleteDeclExternC(S, ND)) {
return false;
}
if (Prev) {
if (!IsGlobal || isIncompleteDeclExternC(S, ND)) {
Previous.clear();
Previous.addDecl(Prev);
return true;
}
if (!isa<VarDecl>(ND))
return false;
} else {
if (IsGlobal) {
IsGlobal = false;
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
I != E; ++I) {
if (isa<VarDecl>(*I)) {
Prev = *I;
break;
}
}
} else {
DeclContext::lookup_result R =
S.Context.getTranslationUnitDecl()->lookup(ND->getDeclName());
for (DeclContext::lookup_result::iterator I = R.begin(), E = R.end();
I != E; ++I) {
if (isa<VarDecl>(*I)) {
Prev = *I;
break;
}
}
}
if (!Prev)
return false;
}
assert(Prev && "should have found a previous declaration to diagnose");
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Prev))
Prev = FD->getFirstDecl();
else
Prev = cast<VarDecl>(Prev)->getFirstDecl();
S.Diag(ND->getLocation(), diag::err_extern_c_global_conflict)
<< IsGlobal << ND;
S.Diag(Prev->getLocation(), diag::note_extern_c_global_conflict)
<< IsGlobal;
return false;
}
template<typename T>
static bool checkForConflictWithNonVisibleExternC(Sema &S, const T *ND,
LookupResult &Previous) {
if (!S.getLangOpts().CPlusPlus) {
if (ND->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
if (NamedDecl *Prev = S.findLocallyScopedExternCDecl(ND->getDeclName())) {
Previous.clear();
Previous.addDecl(Prev);
return true;
}
}
return false;
}
if (ND->getDeclContext()->getRedeclContext()->isTranslationUnit())
return checkGlobalOrExternCConflict(S, ND, true, Previous);
if (isIncompleteDeclExternC(S,ND))
return checkGlobalOrExternCConflict(S, ND, false, Previous);
return false;
}
void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
if (NewVD->isInvalidDecl())
return;
TypeSourceInfo *TInfo = NewVD->getTypeSourceInfo();
QualType T = TInfo->getType();
if (T->isUndeducedType())
return;
if (T->isObjCObjectType()) {
Diag(NewVD->getLocation(), diag::err_statically_allocated_object)
<< FixItHint::CreateInsertion(NewVD->getLocation(), "*");
T = Context.getObjCObjectPointerType(T);
NewVD->setType(T);
}
if (NewVD->hasLocalStorage() && T.getAddressSpace() != 0) {
Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl);
NewVD->setInvalidDecl();
return;
}
if (getLangOpts().OpenCL && NewVD->isFileVarDecl()
&& T.getAddressSpace() != LangAS::opencl_constant
&& !T->isSamplerT()){
Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space);
NewVD->setInvalidDecl();
return;
}
if ((getLangOpts().OpenCLVersion >= 120)
&& NewVD->isStaticLocal()) {
Diag(NewVD->getLocation(), diag::err_static_function_scope);
NewVD->setInvalidDecl();
return;
}
if (NewVD->hasLocalStorage() && T.isObjCGCWeak()
&& !NewVD->hasAttr<BlocksAttr>()) {
if (getLangOpts().getGC() != LangOptions::NonGC)
Diag(NewVD->getLocation(), diag::warn_gc_attribute_weak_on_local);
else {
assert(!getLangOpts().ObjCAutoRefCount);
Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local);
}
}
bool isVM = T->isVariablyModifiedType();
if (isVM || NewVD->hasAttr<CleanupAttr>() ||
NewVD->hasAttr<BlocksAttr>())
getCurFunction()->setHasBranchProtectedScope();
if ((isVM && NewVD->hasLinkage()) ||
(T->isVariableArrayType() && NewVD->hasGlobalStorage())) {
bool SizeIsNegative;
llvm::APSInt Oversized;
TypeSourceInfo *FixedTInfo =
TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context,
SizeIsNegative, Oversized);
if (FixedTInfo == 0 && T->isVariableArrayType()) {
const VariableArrayType *VAT = Context.getAsVariableArrayType(T);
SourceRange SizeRange = VAT->getSizeExpr()->getSourceRange();
if (NewVD->isFileVarDecl())
Diag(NewVD->getLocation(), diag::err_vla_decl_in_file_scope)
<< SizeRange;
else if (NewVD->isStaticLocal())
Diag(NewVD->getLocation(), diag::err_vla_decl_has_static_storage)
<< SizeRange;
else
Diag(NewVD->getLocation(), diag::err_vla_decl_has_extern_linkage)
<< SizeRange;
NewVD->setInvalidDecl();
return;
}
if (FixedTInfo == 0) {
if (NewVD->isFileVarDecl())
Diag(NewVD->getLocation(), diag::err_vm_decl_in_file_scope);
else
Diag(NewVD->getLocation(), diag::err_vm_decl_has_extern_linkage);
NewVD->setInvalidDecl();
return;
}
Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size);
NewVD->setType(FixedTInfo->getType());
NewVD->setTypeSourceInfo(FixedTInfo);
}
if (T->isVoidType()) {
if (NewVD->isThisDeclarationADefinition() || getLangOpts().CPlusPlus) {
Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type)
<< T;
NewVD->setInvalidDecl();
return;
}
}
if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>()) {
Diag(NewVD->getLocation(), diag::err_block_on_nonlocal);
NewVD->setInvalidDecl();
return;
}
if (isVM && NewVD->hasAttr<BlocksAttr>()) {
Diag(NewVD->getLocation(), diag::err_block_on_vm);
NewVD->setInvalidDecl();
return;
}
if (NewVD->isConstexpr() && !T->isDependentType() &&
RequireLiteralType(NewVD->getLocation(), T,
diag::err_constexpr_var_non_literal)) {
NewVD->setInvalidDecl();
return;
}
}
bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) {
CheckVariableDeclarationType(NewVD);
if (NewVD->isInvalidDecl())
return false;
if (Previous.empty() &&
checkForConflictWithNonVisibleExternC(*this, NewVD, Previous))
Previous.setShadowed();
filterNonConflictingPreviousDecls(Context, NewVD, Previous);
if (!Previous.empty()) {
MergeVarDecl(NewVD, Previous);
return true;
}
return false;
}
struct FindOverriddenMethodData {
Sema *S;
CXXMethodDecl *Method;
};
static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
void *UserData) {
RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
FindOverriddenMethodData *Data
= reinterpret_cast<FindOverriddenMethodData*>(UserData);
DeclarationName Name = Data->Method->getDeclName();
if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
QualType T = Data->S->Context.getTypeDeclType(BaseRecord);
CanQualType CT = Data->S->Context.getCanonicalType(T);
Name = Data->S->Context.DeclarationNames.getCXXDestructorName(CT);
}
for (Path.Decls = BaseRecord->lookup(Name);
!Path.Decls.empty();
Path.Decls = Path.Decls.slice(1)) {
NamedDecl *D = Path.Decls.front();
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD, false))
return true;
}
}
return false;
}
namespace {
enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted };
}
static void ReportOverrides(Sema& S, unsigned DiagID, const CXXMethodDecl *MD,
OverrideErrorKind OEK = OEK_All) {
S.Diag(MD->getLocation(), DiagID) << MD->getDeclName();
for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
E = MD->end_overridden_methods();
I != E; ++I) {
if ((OEK == OEK_All) ||
(OEK == OEK_NonDeleted && !(*I)->isDeleted()) ||
(OEK == OEK_Deleted && (*I)->isDeleted()))
S.Diag((*I)->getLocation(), diag::note_overridden_virtual_function);
}
}
bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
CXXBasePaths Paths;
FindOverriddenMethodData Data;
Data.Method = MD;
Data.S = this;
bool hasDeletedOverridenMethods = false;
bool hasNonDeletedOverridenMethods = false;
bool AddedAny = false;
if (DC->lookupInBases(&FindOverriddenMethod, &Data, Paths)) {
for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(),
E = Paths.found_decls_end(); I != E; ++I) {
if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
MD->addOverriddenMethod(OldMD->getCanonicalDecl());
if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
!CheckOverridingFunctionAttributes(MD, OldMD) &&
!CheckOverridingFunctionExceptionSpec(MD, OldMD) &&
!CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) {
hasDeletedOverridenMethods |= OldMD->isDeleted();
hasNonDeletedOverridenMethods |= !OldMD->isDeleted();
AddedAny = true;
}
}
}
}
if (hasDeletedOverridenMethods && !MD->isDeleted()) {
ReportOverrides(*this, diag::err_non_deleted_override, MD, OEK_Deleted);
}
if (hasNonDeletedOverridenMethods && MD->isDeleted()) {
ReportOverrides(*this, diag::err_deleted_override, MD, OEK_NonDeleted);
}
return AddedAny;
}
namespace {
struct ActOnFDArgs {
Scope *S;
Declarator &D;
MultiTemplateParamsArg TemplateParamLists;
bool AddToScope;
};
}
namespace {
class DifferentNameValidatorCCC : public CorrectionCandidateCallback {
public:
DifferentNameValidatorCCC(ASTContext &Context, FunctionDecl *TypoFD,
CXXRecordDecl *Parent)
: Context(Context), OriginalFD(TypoFD),
ExpectedParent(Parent ? Parent->getCanonicalDecl() : 0) {}
virtual bool ValidateCandidate(const TypoCorrection &candidate) {
if (candidate.getEditDistance() == 0)
return false;
SmallVector<unsigned, 1> MismatchedParams;
for (TypoCorrection::const_decl_iterator CDecl = candidate.begin(),
CDeclEnd = candidate.end();
CDecl != CDeclEnd; ++CDecl) {
FunctionDecl *FD = dyn_cast<FunctionDecl>(*CDecl);
if (FD && !FD->hasBody() &&
hasSimilarParameters(Context, FD, OriginalFD, MismatchedParams)) {
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
CXXRecordDecl *Parent = MD->getParent();
if (Parent && Parent->getCanonicalDecl() == ExpectedParent)
return true;
} else if (!ExpectedParent) {
return true;
}
}
}
return false;
}
private:
ASTContext &Context;
FunctionDecl *OriginalFD;
CXXRecordDecl *ExpectedParent;
};
}
static NamedDecl *DiagnoseInvalidRedeclaration(
Sema &SemaRef, LookupResult &Previous, FunctionDecl *NewFD,
ActOnFDArgs &ExtraArgs, bool IsLocalFriend, Scope *S) {
DeclarationName Name = NewFD->getDeclName();
DeclContext *NewDC = NewFD->getDeclContext();
SmallVector<unsigned, 1> MismatchedParams;
SmallVector<std::pair<FunctionDecl *, unsigned>, 1> NearMatches;
TypoCorrection Correction;
bool IsDefinition = ExtraArgs.D.isFunctionDefinition();
unsigned DiagMsg = IsLocalFriend ? diag::err_no_matching_local_friend
: diag::err_member_decl_does_not_match;
LookupResult Prev(SemaRef, Name, NewFD->getLocation(),
IsLocalFriend ? Sema::LookupLocalFriendName
: Sema::LookupOrdinaryName,
Sema::ForRedeclaration);
NewFD->setInvalidDecl();
if (IsLocalFriend)
SemaRef.LookupName(Prev, S);
else
SemaRef.LookupQualifiedName(Prev, NewDC);
assert(!Prev.isAmbiguous() &&
"Cannot have an ambiguity in previous-declaration lookup");
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
DifferentNameValidatorCCC Validator(SemaRef.Context, NewFD,
MD ? MD->getParent() : 0);
if (!Prev.empty()) {
for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
Func != FuncEnd; ++Func) {
FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func);
if (FD &&
hasSimilarParameters(SemaRef.Context, FD, NewFD, MismatchedParams)) {
unsigned ParamNum =
MismatchedParams.empty() ? 0 : MismatchedParams.front() + 1;
NearMatches.push_back(std::make_pair(FD, ParamNum));
}
}
} else if ((Correction = SemaRef.CorrectTypo(
Prev.getLookupNameInfo(), Prev.getLookupKind(), S,
&ExtraArgs.D.getCXXScopeSpec(), Validator,
IsLocalFriend ? 0 : NewDC))) {
ExtraArgs.D.SetIdentifier(Correction.getCorrectionAsIdentifierInfo(),
ExtraArgs.D.getIdentifierLoc());
Previous.clear();
Previous.setLookupName(Correction.getCorrection());
for (TypoCorrection::decl_iterator CDecl = Correction.begin(),
CDeclEnd = Correction.end();
CDecl != CDeclEnd; ++CDecl) {
FunctionDecl *FD = dyn_cast<FunctionDecl>(*CDecl);
if (FD && !FD->hasBody() &&
hasSimilarParameters(SemaRef.Context, FD, NewFD, MismatchedParams)) {
Previous.addDecl(FD);
}
}
bool wasRedeclaration = ExtraArgs.D.isRedeclaration();
NamedDecl *Result;
{
Sema::SFINAETrap Trap(SemaRef);
Result = SemaRef.ActOnFunctionDeclarator(
ExtraArgs.S, ExtraArgs.D,
Correction.getCorrectionDecl()->getDeclContext(),
NewFD->getTypeSourceInfo(), Previous, ExtraArgs.TemplateParamLists,
ExtraArgs.AddToScope);
if (Trap.hasErrorOccurred())
Result = 0;
}
if (Result) {
Decl *Canonical = Result->getCanonicalDecl();
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
I != E; ++I)
if ((*I)->getCanonicalDecl() == Canonical)
Correction.setCorrectionDecl(*I);
SemaRef.diagnoseTypo(
Correction,
SemaRef.PDiag(IsLocalFriend
? diag::err_no_matching_local_friend_suggest
: diag::err_member_decl_does_not_match_suggest)
<< Name << NewDC << IsDefinition);
return Result;
}
ExtraArgs.D.SetIdentifier(Name.getAsIdentifierInfo(),
ExtraArgs.D.getIdentifierLoc());
ExtraArgs.D.setRedeclaration(wasRedeclaration);
Previous.clear();
Previous.setLookupName(Name);
}
SemaRef.Diag(NewFD->getLocation(), DiagMsg)
<< Name << NewDC << IsDefinition << NewFD->getLocation();
bool NewFDisConst = false;
if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD))
NewFDisConst = NewMD->isConst();
for (SmallVectorImpl<std::pair<FunctionDecl *, unsigned> >::iterator
NearMatch = NearMatches.begin(), NearMatchEnd = NearMatches.end();
NearMatch != NearMatchEnd; ++NearMatch) {
FunctionDecl *FD = NearMatch->first;
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
bool FDisConst = MD && MD->isConst();
bool IsMember = MD || !IsLocalFriend;
if (unsigned Idx = NearMatch->second) {
ParmVarDecl *FDParam = FD->getParamDecl(Idx-1);
SourceLocation Loc = FDParam->getTypeSpecStartLoc();
if (Loc.isInvalid()) Loc = FD->getLocation();
SemaRef.Diag(Loc, IsMember ? diag::note_member_def_close_param_match
: diag::note_local_decl_close_param_match)
<< Idx << FDParam->getType()
<< NewFD->getParamDecl(Idx - 1)->getType();
} else if (FDisConst != NewFDisConst) {
SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match)
<< NewFDisConst << FD->getSourceRange().getEnd();
} else
SemaRef.Diag(FD->getLocation(),
IsMember ? diag::note_member_def_close_match
: diag::note_local_decl_close_match);
}
return 0;
}
static FunctionDecl::StorageClass getFunctionStorageClass(Sema &SemaRef,
Declarator &D) {
switch (D.getDeclSpec().getStorageClassSpec()) {
default: llvm_unreachable("Unknown storage class!");
case DeclSpec::SCS_auto:
case DeclSpec::SCS_register:
case DeclSpec::SCS_mutable:
SemaRef.Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::err_typecheck_sclass_func);
D.setInvalidType();
break;
case DeclSpec::SCS_unspecified: break;
case DeclSpec::SCS_extern:
if (D.getDeclSpec().isExternInLinkageSpec())
return SC_None;
return SC_Extern;
case DeclSpec::SCS_static: {
if (SemaRef.CurContext->getRedeclContext()->isFunctionOrMethod()) {
SemaRef.Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::err_static_block_func);
break;
} else
return SC_Static;
}
case DeclSpec::SCS_private_extern: return SC_PrivateExtern;
}
return SC_None;
}
static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
DeclContext *DC, QualType &R,
TypeSourceInfo *TInfo,
FunctionDecl::StorageClass SC,
bool &IsVirtualOkay) {
DeclarationNameInfo NameInfo = SemaRef.GetNameForDeclarator(D);
DeclarationName Name = NameInfo.getName();
FunctionDecl *NewFD = 0;
bool isInline = D.getDeclSpec().isInlineSpecified();
if (!SemaRef.getLangOpts().CPlusPlus) {
bool HasPrototype =
(D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) ||
(!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType());
NewFD = FunctionDecl::Create(SemaRef.Context, DC,
D.getLocStart(), NameInfo, R,
TInfo, SC, isInline,
HasPrototype, false);
if (D.isInvalidType())
NewFD->setInvalidDecl();
NewFD->setLexicalDeclContext(SemaRef.CurContext);
return NewFD;
}
bool isExplicit = D.getDeclSpec().isExplicitSpecified();
bool isConstexpr = D.getDeclSpec().isConstexprSpecified();
if (!DC->isRecord() &&
SemaRef.RequireNonAbstractType(
D.getIdentifierLoc(), R->getAs<FunctionType>()->getReturnType(),
diag::err_abstract_type_in_decl, SemaRef.AbstractReturnType))
D.setInvalidType();
if (Name.getNameKind() == DeclarationName::CXXConstructorName) {
assert(DC->isRecord() &&
"Constructors can only be declared in a member context");
R = SemaRef.CheckConstructorDeclarator(D, R, SC);
return CXXConstructorDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC),
D.getLocStart(), NameInfo,
R, TInfo, isExplicit, isInline,
false,
isConstexpr);
} else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
if (DC->isRecord()) {
R = SemaRef.CheckDestructorDeclarator(D, R, SC);
CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
CXXDestructorDecl *NewDD = CXXDestructorDecl::Create(
SemaRef.Context, Record,
D.getLocStart(),
NameInfo, R, TInfo, isInline,
false);
if (SemaRef.getLangOpts().CPlusPlus11 && !Record->isDependentType() &&
Record->getDefinition() && !Record->isBeingDefined() &&
R->getAs<FunctionProtoType>()->getExceptionSpecType() == EST_None) {
SemaRef.AdjustDestructorExceptionSpec(Record, NewDD);
}
if (SemaRef.Context.getTargetInfo().getCXXABI().isMicrosoft() &&
!Record->isDependentType() && Record->getDefinition() &&
!Record->isBeingDefined() && !NewDD->isDeleted()) {
SemaRef.CheckDestructor(NewDD);
}
IsVirtualOkay = true;
return NewDD;
} else {
SemaRef.Diag(D.getIdentifierLoc(), diag::err_destructor_not_member);
D.setInvalidType();
return FunctionDecl::Create(SemaRef.Context, DC,
D.getLocStart(),
D.getIdentifierLoc(), Name, R, TInfo,
SC, isInline,
true, isConstexpr);
}
} else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
if (!DC->isRecord()) {
SemaRef.Diag(D.getIdentifierLoc(),
diag::err_conv_function_not_member);
return 0;
}
SemaRef.CheckConversionDeclarator(D, R, SC);
IsVirtualOkay = true;
return CXXConversionDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC),
D.getLocStart(), NameInfo,
R, TInfo, isInline, isExplicit,
isConstexpr, SourceLocation());
} else if (DC->isRecord()) {
if (Name.getAsIdentifierInfo() &&
Name.getAsIdentifierInfo() == cast<CXXRecordDecl>(DC)->getIdentifier()){
SemaRef.Diag(D.getIdentifierLoc(), diag::err_constructor_return_type)
<< SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
<< SourceRange(D.getIdentifierLoc());
return 0;
}
CXXMethodDecl *Ret = CXXMethodDecl::Create(SemaRef.Context,
cast<CXXRecordDecl>(DC),
D.getLocStart(), NameInfo, R,
TInfo, SC, isInline,
isConstexpr, SourceLocation());
IsVirtualOkay = !Ret->isStatic();
return Ret;
} else {
return FunctionDecl::Create(SemaRef.Context, DC,
D.getLocStart(),
NameInfo, R, TInfo, SC, isInline,
true, isConstexpr);
}
}
void Sema::checkVoidParamDecl(ParmVarDecl *Param) {
if (getLangOpts().CPlusPlus &&
Param->getType().getUnqualifiedType() != Context.VoidTy) {
bool IsTypeAlias = false;
if (const TypedefType *TT = Param->getType()->getAs<TypedefType>())
IsTypeAlias = isa<TypeAliasDecl>(TT->getDecl());
else if (const TemplateSpecializationType *TST =
Param->getType()->getAs<TemplateSpecializationType>())
IsTypeAlias = TST->isTypeAlias();
Diag(Param->getLocation(), diag::err_param_typedef_of_void)
<< IsTypeAlias;
}
}
enum OpenCLParamType {
ValidKernelParam,
PtrPtrKernelParam,
PtrKernelParam,
InvalidKernelParam,
RecordKernelParam
};
static OpenCLParamType getOpenCLKernelParameterType(QualType PT) {
if (PT->isPointerType()) {
QualType PointeeType = PT->getPointeeType();
return PointeeType->isPointerType() ? PtrPtrKernelParam : PtrKernelParam;
}
if (PT->isImageType())
return PtrKernelParam;
if (PT->isBooleanType())
return InvalidKernelParam;
if (PT->isEventT())
return InvalidKernelParam;
if (PT->isHalfType())
return InvalidKernelParam;
if (PT->isRecordType())
return RecordKernelParam;
return ValidKernelParam;
}
static void checkIsValidOpenCLKernelParameter(
Sema &S,
Declarator &D,
ParmVarDecl *Param,
llvm::SmallPtrSet<const Type *, 16> &ValidTypes) {
QualType PT = Param->getType();
if (ValidTypes.count(PT.getTypePtr()))
return;
switch (getOpenCLKernelParameterType(PT)) {
case PtrPtrKernelParam:
S.Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_param);
D.setInvalidType();
return;
case InvalidKernelParam:
S.Diag(Param->getLocation(), diag::err_bad_kernel_param_type) << PT;
D.setInvalidType();
return;
case PtrKernelParam:
case ValidKernelParam:
ValidTypes.insert(PT.getTypePtr());
return;
case RecordKernelParam:
break;
}
SmallVector<const Decl *, 4> VisitStack;
SmallVector<const FieldDecl *, 4> HistoryStack;
HistoryStack.push_back((const FieldDecl *) 0);
const RecordDecl *PD = PT->castAs<RecordType>()->getDecl();
VisitStack.push_back(PD);
assert(VisitStack.back() && "First decl null?");
do {
const Decl *Next = VisitStack.pop_back_val();
if (!Next) {
assert(!HistoryStack.empty());
if (const FieldDecl *Hist = HistoryStack.pop_back_val())
ValidTypes.insert(Hist->getType().getTypePtr());
continue;
}
const RecordDecl *RD;
if (const FieldDecl *Field = dyn_cast<FieldDecl>(Next)) {
HistoryStack.push_back(Field);
RD = Field->getType()->castAs<RecordType>()->getDecl();
} else {
RD = cast<RecordDecl>(Next);
}
VisitStack.push_back((const Decl *) 0);
for (RecordDecl::field_iterator I = RD->field_begin(),
E = RD->field_end(); I != E; ++I) {
const FieldDecl *FD = *I;
QualType QT = FD->getType();
if (ValidTypes.count(QT.getTypePtr()))
continue;
OpenCLParamType ParamType = getOpenCLKernelParameterType(QT);
if (ParamType == ValidKernelParam)
continue;
if (ParamType == RecordKernelParam) {
VisitStack.push_back(FD);
continue;
}
if (ParamType == PtrKernelParam || ParamType == PtrPtrKernelParam) {
S.Diag(Param->getLocation(),
diag::err_record_with_pointers_kernel_param)
<< PT->isUnionType()
<< PT;
} else {
S.Diag(Param->getLocation(), diag::err_bad_kernel_param_type) << PT;
}
S.Diag(PD->getLocation(), diag::note_within_field_of_type)
<< PD->getDeclName();
for (ArrayRef<const FieldDecl *>::const_iterator I = HistoryStack.begin() + 1,
E = HistoryStack.end(); I != E; ++I) {
const FieldDecl *OuterField = *I;
S.Diag(OuterField->getLocation(), diag::note_within_field_of_type)
<< OuterField->getType();
}
S.Diag(FD->getLocation(), diag::note_illegal_field_declared_here)
<< QT->isPointerType()
<< QT;
D.setInvalidType();
return;
}
} while (!VisitStack.empty());
}
NamedDecl*
Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
TypeSourceInfo *TInfo, LookupResult &Previous,
MultiTemplateParamsArg TemplateParamLists,
bool &AddToScope) {
QualType R = TInfo->getType();
assert(R.getTypePtr()->isFunctionType());
DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
DeclarationName Name = NameInfo.getName();
FunctionDecl::StorageClass SC = getFunctionStorageClass(*this, D);
if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec())
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_invalid_thread)
<< DeclSpec::getSpecifierName(TSCS);
if (D.isFirstDeclarationOfMember())
adjustMemberFunctionCC(R, D.isStaticMember());
bool isFriend = false;
FunctionTemplateDecl *FunctionTemplate = 0;
bool isExplicitSpecialization = false;
bool isFunctionTemplateSpecialization = false;
bool isDependentClassScopeExplicitSpecialization = false;
bool HasExplicitTemplateArgs = false;
TemplateArgumentListInfo TemplateArgs;
bool isVirtualOkay = false;
DeclContext *OriginalDC = DC;
bool IsLocalExternDecl = adjustContextForLocalExternDecl(DC);
FunctionDecl *NewFD = CreateNewFunctionDecl(*this, D, DC, R, TInfo, SC,
isVirtualOkay);
if (!NewFD) return 0;
if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer())
NewFD->setTopLevelDeclInObjCContainer();
NewFD->setLexicalDeclContext(CurContext);
if (IsLocalExternDecl)
NewFD->setLocalExternDecl();
if (getLangOpts().CPlusPlus) {
bool isInline = D.getDeclSpec().isInlineSpecified();
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
bool isExplicit = D.getDeclSpec().isExplicitSpecified();
bool isConstexpr = D.getDeclSpec().isConstexprSpecified();
isFriend = D.getDeclSpec().isFriendSpecified();
if (isFriend && !isInline && D.isFunctionDefinition()) {
NewFD->setImplicitlyInline();
}
if (const CXXRecordDecl *Parent =
dyn_cast<CXXRecordDecl>(NewFD->getDeclContext())) {
if (Parent->isInterface() && cast<CXXMethodDecl>(NewFD)->isUserProvided())
NewFD->setPure(true);
}
SetNestedNameSpecifier(NewFD, D);
isExplicitSpecialization = false;
isFunctionTemplateSpecialization = false;
if (D.isInvalidType())
NewFD->setInvalidDecl();
bool Invalid = false;
if (TemplateParameterList *TemplateParams =
MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
D.getCXXScopeSpec(), TemplateParamLists, isFriend,
isExplicitSpecialization, Invalid)) {
if (TemplateParams->size() > 0) {
if (CheckTemplateDeclScope(S, TemplateParams))
return 0;
if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
Diag(NewFD->getLocation(), diag::err_destructor_template);
return 0;
}
if (DC->isDependentContext()) {
ContextRAII SavedContext(*this, DC);
if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams))
Invalid = true;
}
FunctionTemplate = FunctionTemplateDecl::Create(Context, DC,
NewFD->getLocation(),
Name, TemplateParams,
NewFD);
FunctionTemplate->setLexicalDeclContext(CurContext);
NewFD->setDescribedFunctionTemplate(FunctionTemplate);
if (TemplateParamLists.size() > 1) {
NewFD->setTemplateParameterListsInfo(Context,
TemplateParamLists.size() - 1,
TemplateParamLists.data());
}
} else {
isFunctionTemplateSpecialization = true;
NewFD->setTemplateParameterListsInfo(Context,
TemplateParamLists.size(),
TemplateParamLists.data());
if (isFriend) {
SourceRange RemoveRange = TemplateParams->getSourceRange();
SourceLocation InsertLoc;
if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
InsertLoc = D.getName().getSourceRange().getEnd();
InsertLoc = PP.getLocForEndOfToken(InsertLoc);
}
Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend)
<< Name << RemoveRange
<< FixItHint::CreateRemoval(RemoveRange)
<< FixItHint::CreateInsertion(InsertLoc, "<>");
}
}
}
else {
if (TemplateParamLists.size() > 0)
NewFD->setTemplateParameterListsInfo(Context,
TemplateParamLists.size(),
TemplateParamLists.data());
}
if (Invalid) {
NewFD->setInvalidDecl();
if (FunctionTemplate)
FunctionTemplate->setInvalidDecl();
}
if (isVirtual && !NewFD->isInvalidDecl()) {
if (!isVirtualOkay) {
Diag(D.getDeclSpec().getVirtualSpecLoc(),
diag::err_virtual_non_function);
} else if (!CurContext->isRecord()) {
Diag(D.getDeclSpec().getVirtualSpecLoc(),
diag::err_virtual_out_of_class)
<< FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc());
} else if (NewFD->getDescribedFunctionTemplate()) {
Diag(D.getDeclSpec().getVirtualSpecLoc(),
diag::err_virtual_member_function_template)
<< FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc());
} else {
NewFD->setVirtualAsWritten(true);
}
if (getLangOpts().CPlusPlus1y &&
NewFD->getReturnType()->isUndeducedType())
Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual);
}
if (getLangOpts().CPlusPlus1y &&
(NewFD->isDependentContext() ||
(isFriend && CurContext->isDependentContext())) &&
NewFD->getReturnType()->isUndeducedType()) {
const FunctionProtoType *FPT =
NewFD->getType()->castAs<FunctionProtoType>();
QualType Result =
SubstAutoType(FPT->getReturnType(), Context.DependentTy);
NewFD->setType(Context.getFunctionType(Result, FPT->getParamTypes(),
FPT->getExtProtoInfo()));
}
if (isInline && !NewFD->isInvalidDecl()) {
if (CurContext->isFunctionOrMethod()) {
Diag(D.getDeclSpec().getInlineSpecLoc(),
diag::err_inline_declaration_block_scope) << Name
<< FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc());
}
}
if (isExplicit && !NewFD->isInvalidDecl()) {
if (!CurContext->isRecord()) {
Diag(D.getDeclSpec().getExplicitSpecLoc(),
diag::err_explicit_out_of_class)
<< FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc());
} else if (!isa<CXXConstructorDecl>(NewFD) &&
!isa<CXXConversionDecl>(NewFD)) {
Diag(D.getDeclSpec().getExplicitSpecLoc(),
diag::err_explicit_non_ctor_or_conv_function)
<< FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc());
}
}
if (isConstexpr) {
NewFD->setImplicitlyInline();
if (isa<CXXDestructorDecl>(NewFD))
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor);
}
if (D.getDeclSpec().isModulePrivateSpecified()) {
if (isFunctionTemplateSpecialization) {
SourceLocation ModulePrivateLoc
= D.getDeclSpec().getModulePrivateSpecLoc();
Diag(ModulePrivateLoc, diag::err_module_private_specialization)
<< 0
<< FixItHint::CreateRemoval(ModulePrivateLoc);
} else {
NewFD->setModulePrivate();
if (FunctionTemplate)
FunctionTemplate->setModulePrivate();
}
}
if (isFriend) {
if (FunctionTemplate) {
FunctionTemplate->setObjectOfFriendDecl();
FunctionTemplate->setAccess(AS_public);
}
NewFD->setObjectOfFriendDecl();
NewFD->setAccess(AS_public);
}
switch (D.getFunctionDefinitionKind()) {
case FDK_Declaration:
case FDK_Definition:
break;
case FDK_Defaulted:
NewFD->setDefaulted();
break;
case FDK_Deleted:
NewFD->setDeletedAsWritten();
break;
}
if (isa<CXXMethodDecl>(NewFD) && DC == CurContext &&
D.isFunctionDefinition()) {
NewFD->setImplicitlyInline();
}
if (SC == SC_Static && isa<CXXMethodDecl>(NewFD) &&
!CurContext->isRecord()) {
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::err_static_out_of_line)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
}
const FunctionProtoType *FPT = R->getAs<FunctionProtoType>();
if ((Name.getCXXOverloadedOperator() == OO_Delete ||
Name.getCXXOverloadedOperator() == OO_Array_Delete) &&
getLangOpts().CPlusPlus11 && FPT && !FPT->hasExceptionSpec()) {
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.ExceptionSpecType = EST_BasicNoexcept;
NewFD->setType(Context.getFunctionType(FPT->getReturnType(),
FPT->getParamTypes(), EPI));
}
}
FilterLookupForScope(Previous, OriginalDC, S, shouldConsiderLinkage(NewFD),
D.getCXXScopeSpec().isNotEmpty() ||
isExplicitSpecialization ||
isFunctionTemplateSpecialization);
if (Expr *E = (Expr*) D.getAsmLabel()) {
StringLiteral *SE = cast<StringLiteral>(E);
NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context,
SE->getString(), 0));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
if (I != ExtnameUndeclaredIdentifiers.end()) {
NewFD->addAttr(I->second);
ExtnameUndeclaredIdentifiers.erase(I);
}
}
SmallVector<ParmVarDecl*, 16> Params;
if (D.isFunctionDeclarator()) {
DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
FTI.ArgInfo[0].Param &&
cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) {
checkVoidParamDecl(cast<ParmVarDecl>(FTI.ArgInfo[0].Param));
} else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) {
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
assert(Param->getDeclContext() != NewFD && "Was set before ?");
Param->setDeclContext(NewFD);
Params.push_back(Param);
if (Param->isInvalidDecl())
NewFD->setInvalidDecl();
}
}
} else if (const FunctionProtoType *FT = R->getAs<FunctionProtoType>()) {
for (FunctionProtoType::param_type_iterator AI = FT->param_type_begin(),
AE = FT->param_type_end();
AI != AE; ++AI) {
ParmVarDecl *Param =
BuildParmVarDeclForTypedef(NewFD, D.getIdentifierLoc(), *AI);
Param->setScopeInfo(0, Params.size());
Params.push_back(Param);
}
} else {
assert(R->isFunctionNoProtoType() && NewFD->getNumParams() == 0 &&
"Should not need args for typedef of non-prototype fn");
}
NewFD->setParams(Params);
NewFD->setDeclsInPrototypeScope(DeclsInPrototypeScope);
DeclsInPrototypeScope.clear();
if (D.getDeclSpec().isNoreturnSpecified())
NewFD->addAttr(
::new(Context) C11NoReturnAttr(D.getDeclSpec().getNoreturnSpecLoc(),
Context, 0));
if (!NewFD->isInvalidDecl() &&
NewFD->getReturnType()->isVariablyModifiedType()) {
Diag(NewFD->getLocation(), diag::err_vm_func_decl);
NewFD->setInvalidDecl();
}
ProcessDeclAttributes(S, NewFD, D);
QualType RetType = NewFD->getReturnType();
const CXXRecordDecl *Ret = RetType->isRecordType() ?
RetType->getAsCXXRecordDecl() : RetType->getPointeeCXXRecordDecl();
if (!NewFD->isInvalidDecl() && !NewFD->hasAttr<WarnUnusedResultAttr>() &&
Ret && Ret->hasAttr<WarnUnusedResultAttr>()) {
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
if (!MD || MD->getParent() != Ret) {
NewFD->addAttr(WarnUnusedResultAttr::CreateImplicit(Context));
}
}
if (getLangOpts().OpenCL) {
unsigned AddressSpace = RetType.getAddressSpace();
if (AddressSpace == LangAS::opencl_local ||
AddressSpace == LangAS::opencl_global ||
AddressSpace == LangAS::opencl_constant) {
Diag(NewFD->getLocation(),
diag::err_opencl_return_value_with_address_space);
NewFD->setInvalidDecl();
}
}
if (!getLangOpts().CPlusPlus) {
bool isExplicitSpecialization=false;
if (!NewFD->isInvalidDecl() && NewFD->isMain())
CheckMain(NewFD, D.getDeclSpec());
if (!NewFD->isInvalidDecl() && NewFD->isMSVCRTEntryPoint())
CheckMSVCRTEntryPoint(NewFD);
if (!NewFD->isInvalidDecl())
D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous,
isExplicitSpecialization));
else if (!Previous.empty())
D.setRedeclaration(true);
assert((NewFD->isInvalidDecl() || !D.isRedeclaration() ||
Previous.getResultKind() != LookupResult::FoundOverloaded) &&
"previous declaration set still overloaded");
} else {
if (D.getDeclSpec().isInlineSpecified() &&
NewFD->isReplaceableGlobalAllocationFunction() &&
!NewFD->hasAttr<UsedAttr>())
Diag(D.getDeclSpec().getInlineSpecLoc(),
diag::ext_operator_new_delete_declared_inline)
<< NewFD->getDeclName();
if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
TemplateId->NumArgs);
translateTemplateArguments(TemplateArgsPtr,
TemplateArgs);
HasExplicitTemplateArgs = true;
if (NewFD->isInvalidDecl()) {
HasExplicitTemplateArgs = false;
} else if (FunctionTemplate) {
Diag(D.getIdentifierLoc(), diag::err_function_template_partial_spec)
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc);
HasExplicitTemplateArgs = false;
} else if (!isFunctionTemplateSpecialization &&
!D.getDeclSpec().isFriendSpecified()) {
Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
<< FixItHint::CreateInsertion(
D.getDeclSpec().getLocStart(),
"template<> ");
isFunctionTemplateSpecialization = true;
} else {
isFunctionTemplateSpecialization = true;
}
} else if (isFriend && isFunctionTemplateSpecialization) {
HasExplicitTemplateArgs = true;
TemplateArgs.setLAngleLoc(D.getIdentifierLoc());
TemplateArgs.setRAngleLoc(D.getIdentifierLoc());
}
bool InstantiationDependent = false;
if (isFunctionTemplateSpecialization && isFriend &&
(NewFD->getType()->isDependentType() || DC->isDependentContext() ||
TemplateSpecializationType::anyDependentTemplateArguments(
TemplateArgs.getArgumentArray(), TemplateArgs.size(),
InstantiationDependent))) {
assert(HasExplicitTemplateArgs &&
"friend function specialization without template args");
if (CheckDependentFunctionTemplateSpecialization(NewFD, TemplateArgs,
Previous))
NewFD->setInvalidDecl();
} else if (isFunctionTemplateSpecialization) {
if (CurContext->isDependentContext() && CurContext->isRecord()
&& !isFriend) {
isDependentClassScopeExplicitSpecialization = true;
Diag(NewFD->getLocation(), getLangOpts().MicrosoftExt ?
diag::ext_function_specialization_in_class :
diag::err_function_specialization_in_class)
<< NewFD->getDeclName();
} else if (CheckFunctionTemplateSpecialization(NewFD,
(HasExplicitTemplateArgs ? &TemplateArgs : 0),
Previous))
NewFD->setInvalidDecl();
FunctionTemplateSpecializationInfo *Info =
NewFD->getTemplateSpecializationInfo();
if (Info && SC != SC_None) {
if (SC != Info->getTemplate()->getTemplatedDecl()->getStorageClass())
Diag(NewFD->getLocation(),
diag::err_explicit_specialization_inconsistent_storage_class)
<< SC
<< FixItHint::CreateRemoval(
D.getDeclSpec().getStorageClassSpecLoc());
else
Diag(NewFD->getLocation(),
diag::ext_explicit_specialization_storage_class)
<< FixItHint::CreateRemoval(
D.getDeclSpec().getStorageClassSpecLoc());
}
} else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD)) {
if (CheckMemberSpecialization(NewFD, Previous))
NewFD->setInvalidDecl();
}
if (!isDependentClassScopeExplicitSpecialization) {
if (!NewFD->isInvalidDecl() && NewFD->isMain())
CheckMain(NewFD, D.getDeclSpec());
if (!NewFD->isInvalidDecl() && NewFD->isMSVCRTEntryPoint())
CheckMSVCRTEntryPoint(NewFD);
if (!NewFD->isInvalidDecl())
D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous,
isExplicitSpecialization));
}
assert((NewFD->isInvalidDecl() || !D.isRedeclaration() ||
Previous.getResultKind() != LookupResult::FoundOverloaded) &&
"previous declaration set still overloaded");
NamedDecl *PrincipalDecl = (FunctionTemplate
? cast<NamedDecl>(FunctionTemplate)
: NewFD);
if (isFriend && D.isRedeclaration()) {
AccessSpecifier Access = AS_public;
if (!NewFD->isInvalidDecl())
Access = NewFD->getPreviousDecl()->getAccess();
NewFD->setAccess(Access);
if (FunctionTemplate) FunctionTemplate->setAccess(Access);
}
if (NewFD->isOverloadedOperator() && !DC->isRecord() &&
PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
PrincipalDecl->setNonMemberOperator();
if (FunctionTemplate) {
FunctionTemplateDecl *PrevTemplate =
FunctionTemplate->getPreviousDecl();
CheckTemplateParameterList(FunctionTemplate->getTemplateParameters(),
PrevTemplate ? PrevTemplate->getTemplateParameters() : 0,
D.getDeclSpec().isFriendSpecified()
? (D.isFunctionDefinition()
? TPC_FriendFunctionTemplateDefinition
: TPC_FriendFunctionTemplate)
: (D.getCXXScopeSpec().isSet() &&
DC && DC->isRecord() &&
DC->isDependentContext())
? TPC_ClassTemplateMember
: TPC_FunctionTemplate);
}
if (NewFD->isInvalidDecl()) {
} else if (!D.isRedeclaration()) {
struct ActOnFDArgs ExtraArgs = { S, D, TemplateParamLists,
AddToScope };
if (isa<CXXRecordDecl>(NewFD->getDeclContext()))
NewFD->setAccess(AS_public);
if (D.getCXXScopeSpec().isSet()) {
if (isFriend &&
(TemplateParamLists.size() ||
D.getCXXScopeSpec().getScopeRep()->isDependent() ||
CurContext->isDependentContext())) {
} else {
if (NamedDecl *Result = DiagnoseInvalidRedeclaration(
*this, Previous, NewFD, ExtraArgs, false, 0)) {
AddToScope = ExtraArgs.AddToScope;
return Result;
}
}
} else if (isFriend && cast<CXXRecordDecl>(CurContext)->isLocalClass()) {
if (NamedDecl *Result = DiagnoseInvalidRedeclaration(
*this, Previous, NewFD, ExtraArgs, true, S)) {
AddToScope = ExtraArgs.AddToScope;
return Result;
}
}
} else if (!D.isFunctionDefinition() &&
isa<CXXMethodDecl>(NewFD) && NewFD->isOutOfLine() &&
!isFriend && !isFunctionTemplateSpecialization &&
!isExplicitSpecialization) {
Diag(NewFD->getLocation(), diag::ext_out_of_line_declaration)
<< D.getCXXScopeSpec().getRange();
}
}
ProcessPragmaWeak(S, NewFD);
checkAttributesAfterMerging(*this, *NewFD);
AddKnownFunctionAttributes(NewFD);
if (NewFD->hasAttr<OverloadableAttr>() &&
!NewFD->getType()->getAs<FunctionProtoType>()) {
Diag(NewFD->getLocation(),
diag::err_attribute_overloadable_no_prototype)
<< NewFD;
const FunctionType *FT = NewFD->getType()->getAs<FunctionType>();
FunctionProtoType::ExtProtoInfo EPI(
Context.getDefaultCallingConvention(true, false));
EPI.Variadic = true;
EPI.ExtInfo = FT->getExtInfo();
QualType R = Context.getFunctionType(FT->getReturnType(), None, EPI);
NewFD->setType(R);
}
if (!DC->isRecord() && NewFD->isExternallyVisible())
AddPushedVisibilityAttribute(NewFD);
AddCFAuditedAttribute(NewFD);
if (NewFD->isFirstDecl() && !NewFD->isInvalidDecl() &&
isIncompleteDeclExternC(*this, NewFD))
RegisterLocallyScopedExternCDecl(NewFD, S);
NewFD->setRangeEnd(D.getSourceRange().getEnd());
if (getLangOpts().CPlusPlus) {
if (FunctionTemplate) {
if (NewFD->isInvalidDecl())
FunctionTemplate->setInvalidDecl();
return FunctionTemplate;
}
}
if (NewFD->hasAttr<OpenCLKernelAttr>()) {
if ((getLangOpts().OpenCLVersion >= 120)
&& (SC == SC_Static)) {
Diag(D.getIdentifierLoc(), diag::err_static_kernel);
D.setInvalidType();
}
if (!NewFD->getReturnType()->isVoidType()) {
Diag(D.getIdentifierLoc(),
diag::err_expected_kernel_void_return_type);
D.setInvalidType();
}
llvm::SmallPtrSet<const Type *, 16> ValidTypes;
for (FunctionDecl::param_iterator PI = NewFD->param_begin(),
PE = NewFD->param_end(); PI != PE; ++PI) {
ParmVarDecl *Param = *PI;
checkIsValidOpenCLKernelParameter(*this, D, Param, ValidTypes);
}
}
MarkUnusedFileScopedDecl(NewFD);
if (getLangOpts().CUDA)
if (IdentifierInfo *II = NewFD->getIdentifier())
if (!NewFD->isInvalidDecl() &&
NewFD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
if (II->isStr("cudaConfigureCall")) {
if (!R->getAs<FunctionType>()->getReturnType()->isScalarType())
Diag(NewFD->getLocation(), diag::err_config_scalar_return);
Context.setcudaConfigureCallDecl(NewFD);
}
}
if (isDependentClassScopeExplicitSpecialization) {
ClassScopeFunctionSpecializationDecl *NewSpec =
ClassScopeFunctionSpecializationDecl::Create(
Context, CurContext, SourceLocation(),
cast<CXXMethodDecl>(NewFD),
HasExplicitTemplateArgs, TemplateArgs);
CurContext->addDecl(NewSpec);
AddToScope = false;
}
return NewFD;
}
bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
LookupResult &Previous,
bool IsExplicitSpecialization) {
assert(!NewFD->getReturnType()->isVariablyModifiedType() &&
"Variably modified return types are not handled here");
bool MergeTypeWithPrevious = !getLangOpts().CPlusPlus &&
!Previous.isShadowed();
filterNonConflictingPreviousDecls(Context, NewFD, Previous);
bool Redeclaration = false;
NamedDecl *OldDecl = 0;
if (!Previous.empty()) {
if (!AllowOverloadingOfFunction(Previous, Context)) {
NamedDecl *Candidate = Previous.getFoundDecl();
if (shouldLinkPossiblyHiddenDecl(Candidate, NewFD)) {
Redeclaration = true;
OldDecl = Candidate;
}
} else {
switch (CheckOverload(S, NewFD, Previous, OldDecl,
false)) {
case Ovl_Match:
Redeclaration = true;
break;
case Ovl_NonFunction:
Redeclaration = true;
break;
case Ovl_Overload:
Redeclaration = false;
break;
}
if (!getLangOpts().CPlusPlus && !NewFD->hasAttr<OverloadableAttr>()) {
Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
<< Redeclaration << NewFD;
NamedDecl *OverloadedDecl = 0;
if (Redeclaration)
OverloadedDecl = OldDecl;
else if (!Previous.empty())
OverloadedDecl = Previous.getRepresentativeDecl();
if (OverloadedDecl)
Diag(OverloadedDecl->getLocation(),
diag::note_attribute_overloadable_prev_overload);
NewFD->addAttr(OverloadableAttr::CreateImplicit(Context));
}
}
}
if (!Redeclaration &&
checkForConflictWithNonVisibleExternC(*this, NewFD, Previous)) {
filterNonConflictingPreviousDecls(Context, NewFD, Previous);
if (!Previous.empty()) {
Redeclaration = true;
OldDecl = Previous.getFoundDecl();
MergeTypeWithPrevious = false;
if (OldDecl->hasAttr<OverloadableAttr>()) {
if (!getLangOpts().CPlusPlus && !NewFD->hasAttr<OverloadableAttr>()) {
Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
<< Redeclaration << NewFD;
Diag(Previous.getFoundDecl()->getLocation(),
diag::note_attribute_overloadable_prev_overload);
NewFD->addAttr(OverloadableAttr::CreateImplicit(Context));
}
if (IsOverload(NewFD, cast<FunctionDecl>(OldDecl), false)) {
Redeclaration = false;
OldDecl = 0;
}
}
}
}
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
if (!getLangOpts().CPlusPlus1y && MD && MD->isConstexpr() &&
!MD->isStatic() && !isa<CXXConstructorDecl>(MD) &&
(MD->getTypeQualifiers() & Qualifiers::Const) == 0) {
CXXMethodDecl *OldMD = 0;
if (OldDecl)
OldMD = dyn_cast<CXXMethodDecl>(OldDecl->getAsFunction());
if (!OldMD || !OldMD->isStatic()) {
const FunctionProtoType *FPT =
MD->getType()->castAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.TypeQuals |= Qualifiers::Const;
MD->setType(Context.getFunctionType(FPT->getReturnType(),
FPT->getParamTypes(), EPI));
if (ActiveTemplateInstantiations.empty()) {
SourceLocation AddConstLoc;
if (FunctionTypeLoc FTL = MD->getTypeSourceInfo()->getTypeLoc()
.IgnoreParens().getAs<FunctionTypeLoc>())
AddConstLoc = PP.getLocForEndOfToken(FTL.getRParenLoc());
Diag(MD->getLocation(), diag::warn_cxx1y_compat_constexpr_not_const)
<< FixItHint::CreateInsertion(AddConstLoc, " const");
}
}
}
if (Redeclaration) {
if (MergeFunctionDecl(NewFD, OldDecl, S, MergeTypeWithPrevious)) {
NewFD->setInvalidDecl();
return Redeclaration;
}
Previous.clear();
Previous.addDecl(OldDecl);
if (FunctionTemplateDecl *OldTemplateDecl
= dyn_cast<FunctionTemplateDecl>(OldDecl)) {
NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
FunctionTemplateDecl *NewTemplateDecl
= NewFD->getDescribedFunctionTemplate();
assert(NewTemplateDecl && "Template/non-template mismatch");
if (CXXMethodDecl *Method
= dyn_cast<CXXMethodDecl>(NewTemplateDecl->getTemplatedDecl())) {
Method->setAccess(OldTemplateDecl->getAccess());
NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
}
if (IsExplicitSpecialization &&
NewTemplateDecl->getInstantiatedFromMemberTemplate()) {
NewTemplateDecl->setMemberSpecialization();
assert(OldTemplateDecl->isMemberSpecialization());
}
} else {
NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
if (isa<CXXMethodDecl>(NewFD)) {
CXXMethodDecl *oldMethod = cast<CXXMethodDecl>(OldDecl);
NewFD->setAccess(oldMethod->getAccess());
if (NewFD->isInlined() &&
!Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline()) {
oldMethod = cast<CXXMethodDecl>(oldMethod->getFirstDecl());
if (oldMethod->isVirtual()) {
Context.setNonKeyFunction(oldMethod);
}
}
}
}
}
if (getLangOpts().CPlusPlus) {
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
CheckConstructor(Constructor);
} else if (CXXDestructorDecl *Destructor =
dyn_cast<CXXDestructorDecl>(NewFD)) {
CXXRecordDecl *Record = Destructor->getParent();
QualType ClassType = Context.getTypeDeclType(Record);
if (!ClassType->isDependentType()) {
DeclarationName Name
= Context.DeclarationNames.getCXXDestructorName(
Context.getCanonicalType(ClassType));
if (NewFD->getDeclName() != Name) {
Diag(NewFD->getLocation(), diag::err_destructor_name);
NewFD->setInvalidDecl();
return Redeclaration;
}
}
} else if (CXXConversionDecl *Conversion
= dyn_cast<CXXConversionDecl>(NewFD)) {
ActOnConversionDeclarator(Conversion);
}
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD)) {
if (!Method->isFunctionTemplateSpecialization() &&
!Method->getDescribedFunctionTemplate() &&
Method->isCanonicalDecl()) {
if (AddOverriddenMethods(Method->getParent(), Method)) {
if (NewFD->getStorageClass() == SC_Static) {
ReportOverrides(*this, diag::err_static_overrides_virtual, Method);
}
}
}
if (Method->isStatic())
checkThisInStaticMemberFunctionType(Method);
}
if (NewFD->isOverloadedOperator() &&
CheckOverloadedOperatorDeclaration(NewFD)) {
NewFD->setInvalidDecl();
return Redeclaration;
}
if (NewFD->getLiteralIdentifier() &&
CheckLiteralOperatorDeclaration(NewFD)) {
NewFD->setInvalidDecl();
return Redeclaration;
}
if (!CurContext->isRecord())
CheckCXXDefaultArguments(NewFD);
if (unsigned BuiltinID = NewFD->getBuiltinID()) {
ASTContext::GetBuiltinTypeError Error;
LookupPredefedObjCSuperType(*this, S, NewFD->getIdentifier());
QualType T = Context.GetBuiltinType(BuiltinID, Error);
if (!T.isNull() && !Context.hasSameType(T, NewFD->getType())) {
Context.BuiltinInfo.ForgetBuiltin(BuiltinID, Context.Idents);
}
}
if (NewFD->isExternC() && Previous.empty()) {
QualType R = NewFD->getReturnType();
if (R->isIncompleteType() && !R->isVoidType())
Diag(NewFD->getLocation(), diag::warn_return_value_udt_incomplete)
<< NewFD << R;
else if (!R.isPODType(Context) && !R->isVoidType() &&
!R->isObjCObjectPointerType())
Diag(NewFD->getLocation(), diag::warn_return_value_udt) << NewFD << R;
}
}
return Redeclaration;
}
static SourceRange getResultSourceRange(const FunctionDecl *FD) {
const TypeSourceInfo *TSI = FD->getTypeSourceInfo();
if (!TSI)
return SourceRange();
TypeLoc TL = TSI->getTypeLoc();
FunctionTypeLoc FunctionTL = TL.getAs<FunctionTypeLoc>();
if (!FunctionTL)
return SourceRange();
TypeLoc ResultTL = FunctionTL.getResultLoc();
if (ResultTL.getUnqualifiedLoc().getAs<BuiltinTypeLoc>())
return ResultTL.getSourceRange();
return SourceRange();
}
void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
if (FD->getStorageClass() == SC_Static)
Diag(DS.getStorageClassSpecLoc(), getLangOpts().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());
if (DS.isNoreturnSpecified()) {
SourceLocation NoreturnLoc = DS.getNoreturnSpecLoc();
SourceRange NoreturnRange(NoreturnLoc,
PP.getLocForEndOfToken(NoreturnLoc));
Diag(NoreturnLoc, diag::ext_noreturn_main);
Diag(NoreturnLoc, diag::note_main_remove_noreturn)
<< FixItHint::CreateRemoval(NoreturnRange);
}
if (FD->isConstexpr()) {
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_main)
<< FixItHint::CreateRemoval(DS.getConstexprSpecLoc());
FD->setConstexpr(false);
}
if (getLangOpts().OpenCL) {
Diag(FD->getLocation(), diag::err_opencl_no_main)
<< FD->hasAttr<OpenCLKernelAttr>();
FD->setInvalidDecl();
return;
}
QualType T = FD->getType();
assert(T->isFunctionType() && "function decl is not of function type");
const FunctionType* FT = T->castAs<FunctionType>();
if (Context.hasSameUnqualifiedType(FT->getReturnType(), Context.IntTy)) {
FD->setHasImplicitReturnZero(true);
} else if (getLangOpts().GNUMode && !getLangOpts().CPlusPlus) {
Diag(FD->getTypeSpecStartLoc(), diag::ext_main_returns_nonint);
SourceRange ResultRange = getResultSourceRange(FD);
if (ResultRange.isValid())
Diag(ResultRange.getBegin(), diag::note_main_change_return_type)
<< FixItHint::CreateReplacement(ResultRange, "int");
} else {
SourceRange ResultRange = getResultSourceRange(FD);
if (ResultRange.isValid())
Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint)
<< FixItHint::CreateReplacement(ResultRange, "int");
else
Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint);
FD->setInvalidDecl(true);
}
if (isa<FunctionNoProtoType>(FT)) return;
const FunctionProtoType* FTP = cast<const FunctionProtoType>(FT);
unsigned nparams = FTP->getNumParams();
assert(FD->getNumParams() == nparams);
bool HasExtraParameters = (nparams > 3);
if (nparams == 4 && Context.getTargetInfo().getTriple().isOSDarwin())
HasExtraParameters = false;
if (HasExtraParameters) {
Diag(FD->getLocation(), diag::err_main_surplus_args) << nparams;
FD->setInvalidDecl(true);
nparams = 3;
}
QualType CharPP =
Context.getPointerType(Context.getPointerType(Context.CharTy));
QualType Expected[] = { Context.IntTy, CharPP, CharPP, CharPP };
for (unsigned i = 0; i < nparams; ++i) {
QualType AT = FTP->getParamType(i);
bool mismatch = true;
if (Context.hasSameUnqualifiedType(AT, Expected[i]))
mismatch = false;
else if (Expected[i] == CharPP) {
QualifierCollector qs;
const PointerType* PT;
if ((PT = qs.strip(AT)->getAs<PointerType>()) &&
(PT = qs.strip(PT->getPointeeType())->getAs<PointerType>()) &&
Context.hasSameType(QualType(qs.strip(PT->getPointeeType()), 0),
Context.CharTy)) {
qs.removeConst();
mismatch = !qs.empty();
}
}
if (mismatch) {
Diag(FD->getLocation(), diag::err_main_arg_wrong) << i << Expected[i];
FD->setInvalidDecl(true);
}
}
if (nparams == 1 && !FD->isInvalidDecl()) {
Diag(FD->getLocation(), diag::warn_main_one_arg);
}
if (!FD->isInvalidDecl() && FD->getDescribedFunctionTemplate()) {
Diag(FD->getLocation(), diag::err_mainlike_template_decl) << FD;
FD->setInvalidDecl();
}
}
void Sema::CheckMSVCRTEntryPoint(FunctionDecl *FD) {
QualType T = FD->getType();
assert(T->isFunctionType() && "function decl is not of function type");
const FunctionType *FT = T->castAs<FunctionType>();
if (FT->getReturnType()->isIntegralOrEnumerationType() ||
FT->getReturnType()->isAnyPointerType() ||
FT->getReturnType()->isNullPtrType())
if (FD->getName() != "DllMain")
FD->setHasImplicitReturnZero(true);
if (!FD->isInvalidDecl() && FD->getDescribedFunctionTemplate()) {
Diag(FD->getLocation(), diag::err_mainlike_template_decl) << FD;
FD->setInvalidDecl();
}
}
bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
if (Init->isConstantInitializer(Context, false))
return false;
Diag(Init->getExprLoc(), diag::err_init_element_not_constant)
<< Init->getSourceRange();
return true;
}
namespace {
class SelfReferenceChecker
: public EvaluatedExprVisitor<SelfReferenceChecker> {
Sema &S;
Decl *OrigDecl;
bool isRecordType;
bool isPODType;
bool isReferenceType;
public:
typedef EvaluatedExprVisitor<SelfReferenceChecker> Inherited;
SelfReferenceChecker(Sema &S, Decl *OrigDecl) : Inherited(S.Context),
S(S), OrigDecl(OrigDecl) {
isPODType = false;
isRecordType = false;
isReferenceType = false;
if (ValueDecl *VD = dyn_cast<ValueDecl>(OrigDecl)) {
isPODType = VD->getType().isPODType(S.Context);
isRecordType = VD->getType()->isRecordType();
isReferenceType = VD->getType()->isReferenceType();
}
}
void HandleValue(Expr *E) {
if (isReferenceType)
return;
E = E->IgnoreParenImpCasts();
if (DeclRefExpr* DRE = dyn_cast<DeclRefExpr>(E)) {
HandleDeclRefExpr(DRE);
return;
}
if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
HandleValue(CO->getTrueExpr());
HandleValue(CO->getFalseExpr());
return;
}
if (isa<MemberExpr>(E)) {
Expr *Base = E->IgnoreParenImpCasts();
while (MemberExpr *ME = dyn_cast<MemberExpr>(Base)) {
if (!isa<FieldDecl>(ME->getMemberDecl()))
return;
Base = ME->getBase()->IgnoreParenImpCasts();
}
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base))
HandleDeclRefExpr(DRE);
return;
}
}
void VisitDeclRefExpr(DeclRefExpr *E) {
if (isReferenceType)
HandleDeclRefExpr(E);
}
void VisitImplicitCastExpr(ImplicitCastExpr *E) {
if (E->getCastKind() == CK_LValueToRValue ||
(isRecordType && E->getCastKind() == CK_NoOp))
HandleValue(E->getSubExpr());
Inherited::VisitImplicitCastExpr(E);
}
void VisitMemberExpr(MemberExpr *E) {
if (E->getType()->canDecayToPointerType()) return;
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(E->getMemberDecl());
bool Warn = (MD && !MD->isStatic());
Expr *Base = E->getBase()->IgnoreParenImpCasts();
while (MemberExpr *ME = dyn_cast<MemberExpr>(Base)) {
if (!isa<FieldDecl>(ME->getMemberDecl()))
Warn = false;
Base = ME->getBase()->IgnoreParenImpCasts();
}
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) {
if (Warn)
HandleDeclRefExpr(DRE);
return;
}
Visit(Base);
}
void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
if (E->getNumArgs() > 0)
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->getArg(0)))
HandleDeclRefExpr(DRE);
Inherited::VisitCXXOperatorCallExpr(E);
}
void VisitUnaryOperator(UnaryOperator *E) {
if (E->getOpcode() == UO_AddrOf && isRecordType &&
isa<MemberExpr>(E->getSubExpr()->IgnoreParens())) {
if (!isPODType)
HandleValue(E->getSubExpr());
return;
}
Inherited::VisitUnaryOperator(E);
}
void VisitObjCMessageExpr(ObjCMessageExpr *E) { return; }
void HandleDeclRefExpr(DeclRefExpr *DRE) {
Decl* ReferenceDecl = DRE->getDecl();
if (OrigDecl != ReferenceDecl) return;
unsigned diag;
if (isReferenceType) {
diag = diag::warn_uninit_self_reference_in_reference_init;
} else if (cast<VarDecl>(OrigDecl)->isStaticLocal()) {
diag = diag::warn_static_self_reference_in_init;
} else {
diag = diag::warn_uninit_self_reference_in_init;
}
S.DiagRuntimeBehavior(DRE->getLocStart(), DRE,
S.PDiag(diag)
<< DRE->getNameInfo().getName()
<< OrigDecl->getLocation()
<< DRE->getSourceRange());
}
};
static void CheckSelfReference(Sema &S, Decl* OrigDecl, Expr *E,
bool DirectInit) {
if (isa<ParmVarDecl>(OrigDecl))
return;
E = E->IgnoreParens();
if (!DirectInit && !cast<VarDecl>(OrigDecl)->getType()->isRecordType())
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
if (ICE->getCastKind() == CK_LValueToRValue)
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr()))
if (DRE->getDecl() == OrigDecl)
return;
SelfReferenceChecker(S, OrigDecl).Visit(E);
}
}
void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
bool DirectInit, bool TypeMayContainAuto) {
if (RealDecl == 0 || RealDecl->isInvalidDecl())
return;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) {
IntegerLiteral *IL;
if ((IL = dyn_cast<IntegerLiteral>(Init)) && IL->getValue() == 0 &&
Context.getCanonicalType(IL->getType()) == Context.IntTy)
CheckPureMethod(Method, Init->getSourceRange());
else {
Diag(Method->getLocation(), diag::err_member_function_initialization)
<< Method->getDeclName() << Init->getSourceRange();
Method->setInvalidDecl();
}
return;
}
VarDecl *VDecl = dyn_cast<VarDecl>(RealDecl);
if (!VDecl) {
assert(!isa<FieldDecl>(RealDecl) && "field init shouldn't get here");
Diag(RealDecl->getLocation(), diag::err_illegal_initializer);
RealDecl->setInvalidDecl();
return;
}
ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
if (TypeMayContainAuto && VDecl->getType()->isUndeducedType()) {
Expr *DeduceInit = Init;
if (CXXDirectInit) {
if (CXXDirectInit->getNumExprs() == 0) {
Diag(CXXDirectInit->getLocStart(),
VDecl->isInitCapture() ? diag::err_init_capture_no_expression
: diag::err_auto_var_init_no_expression)
<< VDecl->getDeclName() << VDecl->getType()
<< VDecl->getSourceRange();
RealDecl->setInvalidDecl();
return;
} else if (CXXDirectInit->getNumExprs() > 1) {
Diag(CXXDirectInit->getExpr(1)->getLocStart(),
VDecl->isInitCapture()
? diag::err_init_capture_multiple_expressions
: diag::err_auto_var_init_multiple_expressions)
<< VDecl->getDeclName() << VDecl->getType()
<< VDecl->getSourceRange();
RealDecl->setInvalidDecl();
return;
} else {
DeduceInit = CXXDirectInit->getExpr(0);
}
}
bool DefaultedToAuto = false;
if (getLangOpts().DebuggerCastResultToId &&
Init->getType() == Context.UnknownAnyTy) {
ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType());
if (Result.isInvalid()) {
VDecl->setInvalidDecl();
return;
}
Init = Result.take();
DefaultedToAuto = true;
}
QualType DeducedType;
if (DeduceAutoType(VDecl->getTypeSourceInfo(), DeduceInit, DeducedType) ==
DAR_Failed)
DiagnoseAutoDeductionFailure(VDecl, DeduceInit);
if (DeducedType.isNull()) {
RealDecl->setInvalidDecl();
return;
}
VDecl->setType(DeducedType);
assert(VDecl->isLinkageValid());
if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl))
VDecl->setInvalidDecl();
if (ActiveTemplateInstantiations.empty() && !DefaultedToAuto &&
DeducedType->isObjCIdType()) {
SourceLocation Loc =
VDecl->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
Diag(Loc, diag::warn_auto_var_is_id)
<< VDecl->getDeclName() << DeduceInit->getSourceRange();
}
if (VarDecl *Old = VDecl->getPreviousDecl()) {
MergeVarDeclTypes(VDecl, Old, false);
}
CheckVariableDeclarationType(VDecl);
if (VDecl->isInvalidDecl())
return;
}
if (VDecl->isLocalVarDecl() && VDecl->hasExternalStorage()) {
Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
VDecl->setInvalidDecl();
return;
}
if (!VDecl->getType()->isDependentType()) {
QualType BaseDeclType = VDecl->getType();
if (const ArrayType *Array = Context.getAsIncompleteArrayType(BaseDeclType))
BaseDeclType = Array->getElementType();
if (RequireCompleteType(VDecl->getLocation(), BaseDeclType,
diag::err_typecheck_decl_incomplete_type)) {
RealDecl->setInvalidDecl();
return;
}
if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(),
diag::err_abstract_type_in_decl,
AbstractVariableType))
VDecl->setInvalidDecl();
}
const VarDecl *Def;
if ((Def = VDecl->getDefinition()) && Def != VDecl) {
Diag(VDecl->getLocation(), diag::err_redefinition)
<< VDecl->getDeclName();
Diag(Def->getLocation(), diag::note_previous_definition);
VDecl->setInvalidDecl();
return;
}
const VarDecl* PrevInit = 0;
if (getLangOpts().CPlusPlus) {
if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) {
Diag(Init->getExprLoc(), diag::err_static_data_member_reinitialization)
<< VDecl->getDeclName();
Diag(PrevInit->getInit()->getExprLoc(), diag::note_previous_initializer) << 0;
return;
}
if (VDecl->hasLocalStorage())
getCurFunction()->setHasBranchProtectedScope();
if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) {
VDecl->setInvalidDecl();
return;
}
}
if (VDecl->getStorageClass() == SC_OpenCLWorkGroupLocal) {
Diag(VDecl->getLocation(), diag::err_local_cant_init);
VDecl->setInvalidDecl();
return;
}
QualType DclT = VDecl->getType(), SavT = DclT;
if (getLangOpts().DebuggerCastResultToId && DclT->isObjCObjectPointerType() &&
Init->getType() == Context.UnknownAnyTy) {
ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType());
if (Result.isInvalid()) {
VDecl->setInvalidDecl();
return;
}
Init = Result.take();
}
if (!VDecl->isInvalidDecl()) {
InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
InitializationKind Kind
= DirectInit ?
CXXDirectInit ? InitializationKind::CreateDirect(VDecl->getLocation(),
Init->getLocStart(),
Init->getLocEnd())
: InitializationKind::CreateDirectList(
VDecl->getLocation())
: InitializationKind::CreateCopy(VDecl->getLocation(),
Init->getLocStart());
MultiExprArg Args = Init;
if (CXXDirectInit)
Args = MultiExprArg(CXXDirectInit->getExprs(),
CXXDirectInit->getNumExprs());
InitializationSequence InitSeq(*this, Entity, Kind, Args);
ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT);
if (Result.isInvalid()) {
VDecl->setInvalidDecl();
return;
}
Init = Result.takeAs<Expr>();
}
if (!VDecl->hasLocalStorage() || VDecl->getType()->isRecordType() ||
VDecl->getType()->isReferenceType()) {
CheckSelfReference(*this, RealDecl, Init, DirectInit);
}
if (!VDecl->isInvalidDecl() && (DclT != SavT))
VDecl->setType(DclT);
if (!VDecl->isInvalidDecl()) {
checkUnsafeAssigns(VDecl->getLocation(), VDecl->getType(), Init);
if (VDecl->hasAttr<BlocksAttr>())
checkRetainCycles(VDecl, Init);
if (VDecl->getType().getObjCLifetime() == Qualifiers::OCL_Strong) {
DiagnosticsEngine::Level Level =
Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
Init->getLocStart());
if (Level != DiagnosticsEngine::Ignored)
getCurFunction()->markSafeWeakUse(Init);
}
}
ExprResult Result = ActOnFinishFullExpr(Init, VDecl->getLocation(),
false,
VDecl->isConstexpr());
if (Result.isInvalid()) {
VDecl->setInvalidDecl();
return;
}
Init = Result.take();
VDecl->setInit(Init);
if (VDecl->isLocalVarDecl()) {
if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl()) {
if (VDecl->getStorageClass() == SC_Static)
CheckForConstantInitializer(Init, DclT);
else if (!getLangOpts().C99 && VDecl->getType()->isAggregateType() &&
isa<InitListExpr>(Init) &&
!Init->isConstantInitializer(Context, false))
Diag(Init->getExprLoc(),
diag::ext_aggregate_init_not_constant)
<< Init->getSourceRange();
}
} else if (VDecl->isStaticDataMember() &&
VDecl->getLexicalDeclContext()->isRecord()) {
if (DclT->isDependentType()) {
} else if (VDecl->isConstexpr()) {
} else if (!DclT.isConstQualified()) {
Diag(VDecl->getLocation(), diag::err_in_class_initializer_non_const)
<< Init->getSourceRange();
VDecl->setInvalidDecl();
} else if (DclT->isIntegralOrEnumerationType()) {
SourceLocation Loc;
if (getLangOpts().CPlusPlus11 && DclT.isVolatileQualified())
Diag(VDecl->getLocation(), diag::err_in_class_initializer_volatile);
else if (Init->isValueDependent())
; else if (Init->isIntegerConstantExpr(Context, &Loc))
; else if (Init->isEvaluatable(Context)) {
Diag(Loc, diag::ext_in_class_initializer_non_constant)
<< Init->getSourceRange();
} else {
Diag(Loc, diag::err_in_class_initializer_non_constant)
<< Init->getSourceRange();
VDecl->setInvalidDecl();
}
} else if (DclT->isFloatingType()) { if (getLangOpts().CPlusPlus11) {
Diag(VDecl->getLocation(),
diag::ext_in_class_initializer_float_type_cxx11)
<< DclT << Init->getSourceRange();
Diag(VDecl->getLocStart(),
diag::note_in_class_initializer_float_type_cxx11)
<< FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr ");
} else {
Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type)
<< DclT << Init->getSourceRange();
if (!Init->isValueDependent() && !Init->isEvaluatable(Context)) {
Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant)
<< Init->getSourceRange();
VDecl->setInvalidDecl();
}
}
} else if (getLangOpts().CPlusPlus11 && DclT->isLiteralType(Context)) {
Diag(VDecl->getLocation(), diag::err_in_class_initializer_literal_type)
<< DclT << Init->getSourceRange()
<< FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr ");
VDecl->setConstexpr(true);
} else {
Diag(VDecl->getLocation(), diag::err_in_class_initializer_bad_type)
<< DclT << Init->getSourceRange();
VDecl->setInvalidDecl();
}
} else if (VDecl->isFileVarDecl()) {
if (VDecl->getStorageClass() == SC_Extern &&
(!getLangOpts().CPlusPlus ||
!(Context.getBaseElementType(VDecl->getType()).isConstQualified() ||
VDecl->isExternC())) &&
!isTemplateInstantiation(VDecl->getTemplateSpecializationKind()))
Diag(VDecl->getLocation(), diag::warn_extern_init);
if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl())
CheckForConstantInitializer(Init, DclT);
else if (VDecl->getTLSKind() == VarDecl::TLS_Static &&
!VDecl->isInvalidDecl() && !DclT->isDependentType() &&
!Init->isValueDependent() && !VDecl->isConstexpr() &&
!Init->isConstantInitializer(
Context, VDecl->getType()->isReferenceType())) {
Diag(VDecl->getLocation(), diag::err_thread_dynamic_init);
if (getLangOpts().CPlusPlus11)
Diag(VDecl->getLocation(), diag::note_use_thread_local);
}
}
if (CXXDirectInit) {
assert(DirectInit && "Call-style initializer must be direct init.");
VDecl->setInitStyle(VarDecl::CallInit);
} else if (DirectInit) {
VDecl->setInitStyle(VarDecl::ListInit);
}
CheckCompleteVariableDeclaration(VDecl);
}
void Sema::ActOnInitializerError(Decl *D) {
if (!D || D->isInvalidDecl()) return;
VarDecl *VD = dyn_cast<VarDecl>(D);
if (!VD) return;
if (ParsingInitForAutoVars.count(D)) {
D->setInvalidDecl();
return;
}
QualType Ty = VD->getType();
if (Ty->isDependentType()) return;
if (RequireCompleteType(VD->getLocation(),
Context.getBaseElementType(Ty),
diag::err_typecheck_decl_incomplete_type)) {
VD->setInvalidDecl();
return;
}
if (RequireNonAbstractType(VD->getLocation(), Ty,
diag::err_abstract_type_in_decl,
AbstractVariableType)) {
VD->setInvalidDecl();
return;
}
}
void Sema::ActOnUninitializedDecl(Decl *RealDecl,
bool TypeMayContainAuto) {
if (RealDecl == 0)
return;
if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) {
QualType Type = Var->getType();
if (TypeMayContainAuto && Type->getContainedAutoType()) {
Diag(Var->getLocation(), diag::err_auto_var_requires_init)
<< Var->getDeclName() << Type;
Var->setInvalidDecl();
return;
}
if (Var->isConstexpr() && !Var->isThisDeclarationADefinition()) {
if (Var->isStaticDataMember())
Diag(Var->getLocation(),
diag::err_constexpr_static_mem_var_requires_init)
<< Var->getDeclName();
else
Diag(Var->getLocation(), diag::err_invalid_constexpr_var_decl);
Var->setInvalidDecl();
return;
}
if (!Var->isInvalidDecl() &&
Var->getType().getAddressSpace() == LangAS::opencl_constant &&
!Var->getInit()) {
Diag(Var->getLocation(), diag::err_opencl_constant_no_init);
Var->setInvalidDecl();
return;
}
switch (Var->isThisDeclarationADefinition()) {
case VarDecl::Definition:
if (!Var->isStaticDataMember() || !Var->getAnyInitializer())
break;
case VarDecl::DeclarationOnly:
if (!Type->isDependentType() && Var->isLocalVarDecl() &&
!Var->hasLinkage() && !Var->isInvalidDecl() &&
RequireCompleteType(Var->getLocation(), Type,
diag::err_typecheck_decl_incomplete_type))
Var->setInvalidDecl();
if (!Type->isDependentType() && !Var->isInvalidDecl() &&
RequireNonAbstractType(Var->getLocation(), Type,
diag::err_abstract_type_in_decl,
AbstractVariableType))
Var->setInvalidDecl();
if (!Type->isDependentType() && !Var->isInvalidDecl() &&
Var->getStorageClass() == SC_PrivateExtern) {
Diag(Var->getLocation(), diag::warn_private_extern);
Diag(Var->getLocation(), diag::note_private_extern);
}
return;
case VarDecl::TentativeDefinition:
if (!Var->isInvalidDecl()) {
if (const IncompleteArrayType *ArrayT
= Context.getAsIncompleteArrayType(Type)) {
if (RequireCompleteType(Var->getLocation(),
ArrayT->getElementType(),
diag::err_illegal_decl_array_incomplete_type))
Var->setInvalidDecl();
} else if (Var->getStorageClass() == SC_Static) {
if (Var->isFirstDecl())
RequireCompleteType(Var->getLocation(), Type,
diag::ext_typecheck_decl_incomplete_type);
}
}
if (!Var->isInvalidDecl())
TentativeDefinitions.push_back(Var);
return;
}
if (Type->isIncompleteArrayType()) {
Diag(Var->getLocation(),
diag::err_typecheck_incomplete_array_needs_initializer);
Var->setInvalidDecl();
return;
}
if (Type->isReferenceType()) {
Diag(Var->getLocation(), diag::err_reference_var_requires_init)
<< Var->getDeclName()
<< SourceRange(Var->getLocation(), Var->getLocation());
Var->setInvalidDecl();
return;
}
if (Type->isDependentType())
return;
if (Var->isInvalidDecl())
return;
if (RequireCompleteType(Var->getLocation(),
Context.getBaseElementType(Type),
diag::err_typecheck_decl_incomplete_type)) {
Var->setInvalidDecl();
return;
}
if (RequireNonAbstractType(Var->getLocation(), Type,
diag::err_abstract_type_in_decl,
AbstractVariableType)) {
Var->setInvalidDecl();
return;
}
if (getLangOpts().CPlusPlus && Var->hasLocalStorage()) {
if (const RecordType *Record
= Context.getBaseElementType(Type)->getAs<RecordType>()) {
CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record->getDecl());
if (!CXXRecord->isPOD())
getCurFunction()->setHasBranchProtectedScope();
}
}
InitializedEntity Entity = InitializedEntity::InitializeVariable(Var);
InitializationKind Kind
= InitializationKind::CreateDefault(Var->getLocation());
InitializationSequence InitSeq(*this, Entity, Kind, None);
ExprResult Init = InitSeq.Perform(*this, Entity, Kind, None);
if (Init.isInvalid())
Var->setInvalidDecl();
else if (Init.get()) {
Var->setInit(MaybeCreateExprWithCleanups(Init.get()));
Var->setInitStyle(VarDecl::CallInit);
}
CheckCompleteVariableDeclaration(Var);
}
}
void Sema::ActOnCXXForRangeDecl(Decl *D) {
VarDecl *VD = dyn_cast<VarDecl>(D);
if (!VD) {
Diag(D->getLocation(), diag::err_for_range_decl_must_be_var);
D->setInvalidDecl();
return;
}
VD->setCXXForRangeDecl(true);
int Error = -1;
switch (VD->getStorageClass()) {
case SC_None:
break;
case SC_Extern:
Error = 0;
break;
case SC_Static:
Error = 1;
break;
case SC_PrivateExtern:
Error = 2;
break;
case SC_Auto:
Error = 3;
break;
case SC_Register:
Error = 4;
break;
case SC_OpenCLWorkGroupLocal:
llvm_unreachable("Unexpected storage class");
}
if (VD->isConstexpr())
Error = 5;
if (Error != -1) {
Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class)
<< VD->getDeclName() << Error;
D->setInvalidDecl();
}
}
void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
if (var->isInvalidDecl()) return;
if (getLangOpts().ObjCAutoRefCount &&
var->hasLocalStorage()) {
switch (var->getType().getObjCLifetime()) {
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
case Qualifiers::OCL_Autoreleasing:
break;
case Qualifiers::OCL_Weak:
case Qualifiers::OCL_Strong:
getCurFunction()->setHasBranchProtectedScope();
break;
}
}
if (var->isThisDeclarationADefinition() &&
var->getDeclContext()->getRedeclContext()->isFileContext() &&
var->isExternallyVisible() && var->hasLinkage() &&
getDiagnostics().getDiagnosticLevel(
diag::warn_missing_variable_declarations,
var->getLocation())) {
VarDecl *prev = var->getPreviousDecl();
while (prev && prev->isThisDeclarationADefinition())
prev = prev->getPreviousDecl();
if (!prev)
Diag(var->getLocation(), diag::warn_missing_variable_declarations) << var;
}
if (var->getTLSKind() == VarDecl::TLS_Static &&
var->getType().isDestructedType()) {
Diag(var->getLocation(), diag::err_thread_nontrivial_dtor);
if (getLangOpts().CPlusPlus11)
Diag(var->getLocation(), diag::note_use_thread_local);
}
if (!getLangOpts().CPlusPlus) return;
QualType type = var->getType();
if (type->isDependentType()) return;
if (var->hasAttr<BlocksAttr>()) {
if (type->isStructureOrClassType()) {
EnterExpressionEvaluationContext scope(*this, PotentiallyEvaluated);
SourceLocation poi = var->getLocation();
Expr *varRef =new (Context) DeclRefExpr(var, false, type, VK_LValue, poi);
ExprResult result
= PerformMoveOrCopyInitialization(
InitializedEntity::InitializeBlock(poi, type, false),
var, var->getType(), varRef, true);
if (!result.isInvalid()) {
result = MaybeCreateExprWithCleanups(result);
Expr *init = result.takeAs<Expr>();
Context.setBlockVarCopyInits(var, init);
}
}
}
Expr *Init = var->getInit();
bool IsGlobal = var->hasGlobalStorage() && !var->isStaticLocal();
QualType baseType = Context.getBaseElementType(type);
if (!var->getDeclContext()->isDependentContext() &&
Init && !Init->isValueDependent()) {
if (IsGlobal && !var->isConstexpr() &&
getDiagnostics().getDiagnosticLevel(diag::warn_global_constructor,
var->getLocation())
!= DiagnosticsEngine::Ignored) {
CXXRecordDecl *RD = baseType->getAsCXXRecordDecl();
if (!(RD && !RD->hasTrivialDestructor()) &&
!Init->isConstantInitializer(Context, baseType->isReferenceType()))
Diag(var->getLocation(), diag::warn_global_constructor)
<< Init->getSourceRange();
}
if (var->isConstexpr()) {
SmallVector<PartialDiagnosticAt, 8> Notes;
if (!var->evaluateValue(Notes) || !var->isInitICE()) {
SourceLocation DiagLoc = var->getLocation();
if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
diag::note_invalid_subexpr_in_const_expr) {
DiagLoc = Notes[0].first;
Notes.clear();
}
Diag(DiagLoc, diag::err_constexpr_var_requires_const_init)
<< var << Init->getSourceRange();
for (unsigned I = 0, N = Notes.size(); I != N; ++I)
Diag(Notes[I].first, Notes[I].second);
}
} else if (var->isUsableInConstantExpressions(Context)) {
var->checkInitIsICE();
}
}
if (const RecordType *recordType = baseType->getAs<RecordType>())
FinalizeVarWithDestructor(var, recordType);
}
void
Sema::FinalizeDeclaration(Decl *ThisDecl) {
ParsingInitForAutoVars.erase(ThisDecl);
VarDecl *VD = dyn_cast_or_null<VarDecl>(ThisDecl);
if (!VD)
return;
checkAttributesAfterMerging(*this, *VD);
if (UsedAttr *Attr = VD->getAttr<UsedAttr>()) {
if (!Attr->isInherited() && !VD->isThisDeclarationADefinition()) {
Diag(Attr->getLocation(), diag::warn_attribute_ignored) << Attr;
VD->dropAttr<UsedAttr>();
}
}
if (!VD->isInvalidDecl() &&
VD->isThisDeclarationADefinition() == VarDecl::TentativeDefinition) {
if (const VarDecl *Def = VD->getDefinition()) {
if (Def->hasAttr<AliasAttr>()) {
Diag(VD->getLocation(), diag::err_tentative_after_alias)
<< VD->getDeclName();
Diag(Def->getLocation(), diag::note_previous_definition);
VD->setInvalidDecl();
}
}
}
const DeclContext *DC = VD->getDeclContext();
if (DC->getRedeclContext()->isFileContext() && VD->isExternallyVisible())
AddPushedVisibilityAttribute(VD);
if (VD->isFileVarDecl())
MarkUnusedFileScopedDecl(VD);
if (!VD->hasAttr<TypeTagForDatatypeAttr>() ||
!VD->getType()->isIntegralOrEnumerationType())
return;
for (specific_attr_iterator<TypeTagForDatatypeAttr>
I = ThisDecl->specific_attr_begin<TypeTagForDatatypeAttr>(),
E = ThisDecl->specific_attr_end<TypeTagForDatatypeAttr>();
I != E; ++I) {
const Expr *MagicValueExpr = VD->getInit();
if (!MagicValueExpr) {
continue;
}
llvm::APSInt MagicValueInt;
if (!MagicValueExpr->isIntegerConstantExpr(MagicValueInt, Context)) {
Diag(I->getRange().getBegin(),
diag::err_type_tag_for_datatype_not_ice)
<< LangOpts.CPlusPlus << MagicValueExpr->getSourceRange();
continue;
}
if (MagicValueInt.getActiveBits() > 64) {
Diag(I->getRange().getBegin(),
diag::err_type_tag_for_datatype_too_large)
<< LangOpts.CPlusPlus << MagicValueExpr->getSourceRange();
continue;
}
uint64_t MagicValue = MagicValueInt.getZExtValue();
RegisterTypeTagForDatatype(I->getArgumentKind(),
MagicValue,
I->getMatchingCType(),
I->getLayoutCompatible(),
I->getMustBeNull());
}
}
Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
ArrayRef<Decl *> Group) {
SmallVector<Decl*, 8> Decls;
if (DS.isTypeSpecOwned())
Decls.push_back(DS.getRepAsDecl());
DeclaratorDecl *FirstDeclaratorInGroup = 0;
for (unsigned i = 0, e = Group.size(); i != e; ++i)
if (Decl *D = Group[i]) {
if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D))
if (!FirstDeclaratorInGroup)
FirstDeclaratorInGroup = DD;
Decls.push_back(D);
}
if (DeclSpec::isDeclRep(DS.getTypeSpecType())) {
if (TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl())) {
HandleTagNumbering(*this, Tag);
if (!Tag->hasNameForLinkage() && !Tag->hasDeclaratorForAnonDecl())
Tag->setDeclaratorForAnonDecl(FirstDeclaratorInGroup);
}
}
return BuildDeclaratorGroup(Decls, DS.containsPlaceholderType());
}
Sema::DeclGroupPtrTy
Sema::BuildDeclaratorGroup(llvm::MutableArrayRef<Decl *> Group,
bool TypeMayContainAuto) {
if (TypeMayContainAuto && Group.size() > 1) {
QualType Deduced;
CanQualType DeducedCanon;
VarDecl *DeducedDecl = 0;
for (unsigned i = 0, e = Group.size(); i != e; ++i) {
if (VarDecl *D = dyn_cast<VarDecl>(Group[i])) {
AutoType *AT = D->getType()->getContainedAutoType();
if (AT && D->isInvalidDecl())
break;
QualType U = AT ? AT->getDeducedType() : QualType();
if (!U.isNull()) {
CanQualType UCanon = Context.getCanonicalType(U);
if (Deduced.isNull()) {
Deduced = U;
DeducedCanon = UCanon;
DeducedDecl = D;
} else if (DeducedCanon != UCanon) {
Diag(D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
diag::err_auto_different_deductions)
<< (AT->isDecltypeAuto() ? 1 : 0)
<< Deduced << DeducedDecl->getDeclName()
<< U << D->getDeclName()
<< DeducedDecl->getInit()->getSourceRange()
<< D->getInit()->getSourceRange();
D->setInvalidDecl();
break;
}
}
}
}
}
ActOnDocumentableDecls(Group);
return DeclGroupPtrTy::make(
DeclGroupRef::Create(Context, Group.data(), Group.size()));
}
void Sema::ActOnDocumentableDecl(Decl *D) {
ActOnDocumentableDecls(D);
}
void Sema::ActOnDocumentableDecls(ArrayRef<Decl *> Group) {
if (Group.empty() || !Group[0])
return;
if (Diags.getDiagnosticLevel(diag::warn_doc_param_not_found,
Group[0]->getLocation())
== DiagnosticsEngine::Ignored)
return;
if (Group.size() >= 2) {
Decl *MaybeTagDecl = Group[0];
if (MaybeTagDecl && isa<TagDecl>(MaybeTagDecl)) {
Group = Group.slice(1);
}
}
ArrayRef<RawComment *> Comments = Context.getRawCommentList().getComments();
if (!Comments.empty() &&
!Comments.back()->isAttached()) {
for (unsigned i = 0, e = Group.size(); i != e; ++i)
Context.getCommentForDecl(Group[i], &PP);
}
}
Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
const DeclSpec &DS = D.getDeclSpec();
VarDecl::StorageClass StorageClass = SC_None;
if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
StorageClass = SC_Register;
} else if (getLangOpts().CPlusPlus &&
DS.getStorageClassSpec() == DeclSpec::SCS_auto) {
StorageClass = SC_Auto;
} else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) {
Diag(DS.getStorageClassSpecLoc(),
diag::err_invalid_storage_class_in_func_decl);
D.getMutableDeclSpec().ClearStorageClassSpecs();
}
if (DeclSpec::TSCS TSCS = DS.getThreadStorageClassSpec())
Diag(DS.getThreadStorageClassSpecLoc(), diag::err_invalid_thread)
<< DeclSpec::getSpecifierName(TSCS);
if (DS.isConstexprSpecified())
Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr)
<< 0;
DiagnoseFunctionSpecifiers(DS);
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType parmDeclType = TInfo->getType();
if (getLangOpts().CPlusPlus) {
CheckExtraCXXDefaultArguments(D);
if (D.getCXXScopeSpec().isSet()) {
Diag(D.getIdentifierLoc(), diag::err_qualified_param_declarator)
<< D.getCXXScopeSpec().getRange();
D.getCXXScopeSpec().clear();
}
}
IdentifierInfo *II = 0;
if (D.hasName()) {
II = D.getIdentifier();
if (!II) {
Diag(D.getIdentifierLoc(), diag::err_bad_parameter_name)
<< GetNameForDeclarator(D).getName();
D.setInvalidType(true);
}
}
if (II) {
LookupResult R(*this, II, D.getIdentifierLoc(), LookupOrdinaryName,
ForRedeclaration);
LookupName(R, S);
if (R.isSingleResult()) {
NamedDecl *PrevDecl = R.getFoundDecl();
if (PrevDecl->isTemplateParameter()) {
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
PrevDecl = 0;
} else if (S->isDeclScope(PrevDecl)) {
Diag(D.getIdentifierLoc(), diag::err_param_redefinition) << II;
Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
II = 0;
D.SetIdentifier(0, D.getIdentifierLoc());
D.setInvalidType(true);
}
}
}
ParmVarDecl *New = CheckParameter(Context.getTranslationUnitDecl(),
D.getLocStart(),
D.getIdentifierLoc(), II,
parmDeclType, TInfo,
StorageClass);
if (D.isInvalidType())
New->setInvalidDecl();
assert(S->isFunctionPrototypeScope());
assert(S->getFunctionPrototypeDepth() >= 1);
New->setScopeInfo(S->getFunctionPrototypeDepth() - 1,
S->getNextFunctionPrototypeIndex());
S->AddDecl(New);
if (II)
IdResolver.AddDecl(New);
ProcessDeclAttributes(S, New, D);
if (D.getDeclSpec().isModulePrivateSpecified())
Diag(New->getLocation(), diag::err_module_private_local)
<< 1 << New->getDeclName()
<< SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
<< FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
if (New->hasAttr<BlocksAttr>()) {
Diag(New->getLocation(), diag::err_block_on_nonlocal);
}
return New;
}
ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC,
SourceLocation Loc,
QualType T) {
ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, Loc, 0,
T, Context.getTrivialTypeSourceInfo(T, Loc),
SC_None, 0);
Param->setImplicit();
return Param;
}
void Sema::DiagnoseUnusedParameters(ParmVarDecl * const *Param,
ParmVarDecl * const *ParamEnd) {
if (!ActiveTemplateInstantiations.empty())
return;
for (; Param != ParamEnd; ++Param) {
if (!(*Param)->isReferenced() && (*Param)->getDeclName() &&
!(*Param)->hasAttr<UnusedAttr>()) {
Diag((*Param)->getLocation(), diag::warn_unused_parameter)
<< (*Param)->getDeclName();
}
}
}
void Sema::DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Param,
ParmVarDecl * const *ParamEnd,
QualType ReturnTy,
NamedDecl *D) {
if (LangOpts.NumLargeByValueCopy == 0) return;
if (!ReturnTy->isDependentType() && ReturnTy.isPODType(Context)) {
unsigned Size = Context.getTypeSizeInChars(ReturnTy).getQuantity();
if (Size > LangOpts.NumLargeByValueCopy)
Diag(D->getLocation(), diag::warn_return_value_size)
<< D->getDeclName() << Size;
}
for (; Param != ParamEnd; ++Param) {
QualType T = (*Param)->getType();
if (T->isDependentType() || !T.isPODType(Context))
continue;
unsigned Size = Context.getTypeSizeInChars(T).getQuantity();
if (Size > LangOpts.NumLargeByValueCopy)
Diag((*Param)->getLocation(), diag::warn_parameter_size)
<< (*Param)->getDeclName() << Size;
}
}
ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
SourceLocation NameLoc, IdentifierInfo *Name,
QualType T, TypeSourceInfo *TSInfo,
VarDecl::StorageClass StorageClass) {
if (getLangOpts().ObjCAutoRefCount &&
T.getObjCLifetime() == Qualifiers::OCL_None &&
T->isObjCLifetimeType()) {
Qualifiers::ObjCLifetime lifetime;
if (T->isArrayType()) {
if (!T.isConstQualified()) {
DelayedDiagnostics.add(
sema::DelayedDiagnostic::makeForbiddenType(
NameLoc, diag::err_arc_array_param_no_ownership, T, false));
}
lifetime = Qualifiers::OCL_ExplicitNone;
} else {
lifetime = T->getObjCARCImplicitLifetime();
}
T = Context.getLifetimeQualifiedType(T, lifetime);
}
ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name,
Context.getAdjustedParameterType(T),
TSInfo,
StorageClass, 0);
if (!CurContext->isRecord() &&
RequireNonAbstractType(NameLoc, T, diag::err_abstract_type_in_decl,
AbstractParamType))
New->setInvalidDecl();
if (T->isObjCObjectType()) {
SourceLocation TypeEndLoc = TSInfo->getTypeLoc().getLocEnd();
Diag(NameLoc,
diag::err_object_cannot_be_passed_returned_by_value) << 1 << T
<< FixItHint::CreateInsertion(TypeEndLoc, "*");
T = Context.getObjCObjectPointerType(T);
New->setType(T);
}
if (T.getAddressSpace() != 0) {
Diag(NameLoc, diag::err_arg_with_address_space);
New->setInvalidDecl();
}
return New;
}
void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
SourceLocation LocAfterDecls) {
DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
if (!FTI.hasPrototype) {
for (int i = FTI.NumArgs; i != 0; ) {
--i;
if (FTI.ArgInfo[i].Param == 0) {
SmallString<256> Code;
llvm::raw_svector_ostream(Code) << " int "
<< FTI.ArgInfo[i].Ident->getName()
<< ";\n";
Diag(FTI.ArgInfo[i].IdentLoc, diag::ext_param_not_declared)
<< FTI.ArgInfo[i].Ident
<< FixItHint::CreateInsertion(LocAfterDecls, Code.str());
AttributeFactory attrs;
DeclSpec DS(attrs);
const char* PrevSpec; unsigned DiagID; DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc,
PrevSpec, DiagID, Context.getPrintingPolicy());
DS.SetRangeStart(FTI.ArgInfo[i].IdentLoc);
DS.SetRangeEnd(FTI.ArgInfo[i].IdentLoc);
Declarator ParamD(DS, Declarator::KNRTypeListContext);
ParamD.SetIdentifier(FTI.ArgInfo[i].Ident, FTI.ArgInfo[i].IdentLoc);
FTI.ArgInfo[i].Param = ActOnParamDeclarator(S, ParamD);
}
}
}
}
Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
assert(getCurFunctionDecl() == 0 && "Function parsing confused");
assert(D.isFunctionDeclarator() && "Not a function declarator!");
Scope *ParentScope = FnBodyScope->getParent();
D.setFunctionDefinitionKind(FDK_Definition);
Decl *DP = HandleDeclarator(ParentScope, D, MultiTemplateParamsArg());
return ActOnStartOfFunctionDef(FnBodyScope, DP);
}
static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,
const FunctionDecl*& PossibleZeroParamPrototype) {
if (FD->isInvalidDecl())
return false;
if (!FD->isGlobal())
return false;
if (isa<CXXMethodDecl>(FD))
return false;
if (FD->isMain())
return false;
if (FD->isInlined())
return false;
if (FD->getDescribedFunctionTemplate())
return false;
if (FD->isFunctionTemplateSpecialization())
return false;
if (FD->hasAttr<OpenCLKernelAttr>())
return false;
bool MissingPrototype = true;
for (const FunctionDecl *Prev = FD->getPreviousDecl();
Prev; Prev = Prev->getPreviousDecl()) {
if (Prev->getLexicalDeclContext()->isFunctionOrMethod())
continue;
MissingPrototype = !Prev->getType()->isFunctionProtoType();
if (FD->getNumParams() == 0)
PossibleZeroParamPrototype = Prev;
break;
}
return MissingPrototype;
}
void
Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
const FunctionDecl *EffectiveDefinition) {
const FunctionDecl *Definition = EffectiveDefinition;
if (!Definition)
if (!FD->isDefined(Definition))
return;
if (canRedefineFunction(Definition, getLangOpts()))
return;
if (getLangOpts().GNUMode && Definition->isInlineSpecified() &&
Definition->getStorageClass() == SC_Extern)
Diag(FD->getLocation(), diag::err_redefinition_extern_inline)
<< FD->getDeclName() << getLangOpts().CPlusPlus;
else
Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName();
Diag(Definition->getLocation(), diag::note_previous_definition);
FD->setInvalidDecl();
}
static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
Sema &S) {
CXXRecordDecl *const LambdaClass = CallOperator->getParent();
LambdaScopeInfo *LSI = S.PushLambdaScope();
LSI->CallOperator = CallOperator;
LSI->Lambda = LambdaClass;
LSI->ReturnType = CallOperator->getReturnType();
const LambdaCaptureDefault LCD = LambdaClass->getLambdaCaptureDefault();
if (LCD == LCD_None)
LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_None;
else if (LCD == LCD_ByCopy)
LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByval;
else if (LCD == LCD_ByRef)
LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByref;
DeclarationNameInfo DNI = CallOperator->getNameInfo();
LSI->IntroducerRange = DNI.getCXXOperatorNameRange();
LSI->Mutable = !CallOperator->isConst();
for (LambdaExpr::capture_iterator C = LambdaClass->captures_begin(),
CEnd = LambdaClass->captures_end(); C != CEnd; ++C) {
if (C->capturesVariable()) {
VarDecl *VD = C->getCapturedVar();
if (VD->isInitCapture())
S.CurrentInstantiationScope->InstantiatedLocal(VD, VD);
QualType CaptureType = VD->getType();
const bool ByRef = C->getCaptureKind() == LCK_ByRef;
LSI->addCapture(VD, false, ByRef,
true, C->getLocation(),
C->isPackExpansion()
? C->getEllipsisLoc() : SourceLocation(),
CaptureType, 0);
} else if (C->capturesThis()) {
LSI->addThisCapture( false, C->getLocation(),
S.getCurrentThisType(), 0);
}
}
}
Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation();
if (!D)
return D;
FunctionDecl *FD = 0;
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
FD = FunTmpl->getTemplatedDecl();
else
FD = cast<FunctionDecl>(D);
if (isGenericLambdaCallOperatorSpecialization(FD)) {
assert(ActiveTemplateInstantiations.size() &&
"There should be an active template instantiation on the stack "
"when instantiating a generic lambda!");
RebuildLambdaScopeInfo(cast<CXXMethodDecl>(D), *this);
}
else
PushFunctionScope();
if (!FD->isLateTemplateParsed())
CheckForFunctionRedefinition(FD);
if (unsigned BuiltinID = FD->getBuiltinID()) {
if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID) &&
!Context.BuiltinInfo.isPredefinedRuntimeFunction(BuiltinID)) {
Diag(FD->getLocation(), diag::err_builtin_definition) << FD;
FD->setInvalidDecl();
}
}
QualType ResultType = FD->getReturnType();
if (!ResultType->isDependentType() && !ResultType->isVoidType() &&
!FD->isInvalidDecl() &&
RequireCompleteType(FD->getLocation(), ResultType,
diag::err_func_def_incomplete_result))
FD->setInvalidDecl();
const FunctionDecl *PossibleZeroParamPrototype = 0;
if (ShouldWarnAboutMissingPrototype(FD, PossibleZeroParamPrototype)) {
Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
if (PossibleZeroParamPrototype) {
if (TypeSourceInfo *TI =
PossibleZeroParamPrototype->getTypeSourceInfo()) {
TypeLoc TL = TI->getTypeLoc();
if (FunctionNoProtoTypeLoc FTL = TL.getAs<FunctionNoProtoTypeLoc>())
Diag(PossibleZeroParamPrototype->getLocation(),
diag::note_declaration_not_a_prototype)
<< PossibleZeroParamPrototype
<< FixItHint::CreateInsertion(FTL.getRParenLoc(), "void");
}
}
}
if (FnBodyScope)
PushDeclContext(FnBodyScope, FD);
CheckParmsForFunctionDef(FD->param_begin(), FD->param_end(),
true);
for (unsigned p = 0, NumParams = FD->getNumParams(); p < NumParams; ++p) {
ParmVarDecl *Param = FD->getParamDecl(p);
Param->setOwningFunction(FD);
if (Param->getIdentifier() && FnBodyScope) {
CheckShadow(FnBodyScope, Param);
PushOnScopeChains(Param, FnBodyScope);
}
}
if (FnBodyScope) {
for (ArrayRef<NamedDecl *>::iterator
I = FD->getDeclsInPrototypeScope().begin(),
E = FD->getDeclsInPrototypeScope().end();
I != E; ++I) {
NamedDecl *D = *I;
if (D->getLexicalDeclContext() == Context.getTranslationUnitDecl()) {
for (DeclContext::decl_iterator DI = Context.getTranslationUnitDecl()->decls_begin(),
DE = Context.getTranslationUnitDecl()->decls_end(); DI != DE; ++DI) {
if (*DI == D) {
Context.getTranslationUnitDecl()->removeDecl(D);
break;
}
}
D->setLexicalDeclContext(CurContext);
}
if (!D->getName().empty())
PushOnScopeChains(D, FnBodyScope, false);
if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
for (EnumDecl::enumerator_iterator EI = ED->enumerator_begin(),
EE = ED->enumerator_end(); EI != EE; ++EI)
PushOnScopeChains(*EI, FnBodyScope, false);
}
}
}
if (const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>())
ResolveExceptionSpec(D->getLocation(), FPT);
DLLImportAttr *DA = FD->getAttr<DLLImportAttr>();
if (DA && (!FD->hasAttr<DLLExportAttr>())) {
if (!DA->isInherited() &&
!(LangOpts.MicrosoftExt && FD->getLexicalDeclContext()->isRecord())) {
Diag(FD->getLocation(),
diag::err_attribute_can_be_applied_only_to_symbol_declaration)
<< DA;
FD->setInvalidDecl();
return D;
}
if (!LangOpts.MicrosoftExt) {
Diag(FD->getLocation(),
diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
<< FD << DA;
}
}
ActOnDocumentableDecl(D);
return D;
}
void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) {
ReturnStmt **Returns = Scope->Returns.data();
const VarDecl *NRVOCandidate = 0;
for (unsigned I = 0, E = Scope->Returns.size(); I != E; ++I) {
if (!Returns[I]->getNRVOCandidate())
return;
if (!NRVOCandidate)
NRVOCandidate = Returns[I]->getNRVOCandidate();
else if (NRVOCandidate != Returns[I]->getNRVOCandidate())
return;
}
if (NRVOCandidate)
const_cast<VarDecl*>(NRVOCandidate)->setNRVOVariable(true);
}
bool Sema::canSkipFunctionBody(Decl *D) {
if (const FunctionDecl *FD = D->getAsFunction())
if (FD->isConstexpr() || FD->getReturnType()->isUndeducedType())
return false;
return Consumer.shouldSkipFunctionBody(D);
}
Decl *Sema::ActOnSkippedFunctionBody(Decl *Decl) {
if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Decl))
FD->setHasSkippedBody();
else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(Decl))
MD->setHasSkippedBody();
return ActOnFinishFunctionBody(Decl, 0);
}
Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) {
return ActOnFinishFunctionBody(D, BodyArg, false);
}
Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
bool IsInstantiation) {
FunctionDecl *FD = dcl ? dcl->getAsFunction() : 0;
sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
sema::AnalysisBasedWarnings::Policy *ActivePolicy = 0;
if (FD) {
FD->setBody(Body);
if (getLangOpts().CPlusPlus1y && !FD->isInvalidDecl() && Body &&
!FD->isDependentContext() && FD->getReturnType()->isUndeducedType()) {
if (!FD->getReturnType()->getAs<AutoType>()) {
Diag(dcl->getLocation(), diag::err_auto_fn_no_return_but_not_auto)
<< FD->getReturnType();
FD->setInvalidDecl();
} else {
TypeLoc ResultType = FD->getTypeSourceInfo()->getTypeLoc().
IgnoreParens().castAs<FunctionProtoTypeLoc>().getResultLoc();
Context.adjustDeducedFunctionResultType(
FD, SubstAutoType(ResultType.getType(), Context.VoidTy));
}
}
if (!FD->isFirstDecl() && FD->getPreviousDecl()->isUsed()) {
if (!FD->isExternallyVisible())
UndefinedButUsed.erase(FD);
else if (FD->isInlined() &&
(LangOpts.CPlusPlus || !LangOpts.GNUInline) &&
(!FD->getPreviousDecl()->hasAttr<GNUInlineAttr>()))
UndefinedButUsed.erase(FD);
}
if (FD->hasImplicitReturnZero() || FD->hasAttr<NakedAttr>())
WP.disableCheckFallThrough();
if (getLangOpts().MicrosoftExt && FD->isPure() && FD->isCanonicalDecl())
Diag(FD->getLocation(), diag::warn_pure_function_definition);
if (!FD->isInvalidDecl()) {
DiagnoseUnusedParameters(FD->param_begin(), FD->param_end());
DiagnoseSizeOfParametersAndReturnValue(FD->param_begin(), FD->param_end(),
FD->getReturnType(), FD);
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(FD))
MarkVTableUsed(FD->getLocation(), Constructor->getParent());
if (getLangOpts().CPlusPlus && FD->getReturnType()->isRecordType() &&
!FD->isDependentContext())
computeNRVO(Body, getCurFunction());
}
assert((FD == getCurFunctionDecl() || getCurLambda()->CallOperator == FD) &&
"Function parsing confused");
} else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) {
assert(MD == getCurMethodDecl() && "Method parsing confused");
MD->setBody(Body);
if (!MD->isInvalidDecl()) {
DiagnoseUnusedParameters(MD->param_begin(), MD->param_end());
DiagnoseSizeOfParametersAndReturnValue(MD->param_begin(), MD->param_end(),
MD->getReturnType(), MD);
if (Body)
computeNRVO(Body, getCurFunction());
}
if (getCurFunction()->ObjCShouldCallSuper) {
Diag(MD->getLocEnd(), diag::warn_objc_missing_super_call)
<< MD->getSelector().getAsString();
getCurFunction()->ObjCShouldCallSuper = false;
}
if (getCurFunction()->ObjCWarnForNoDesignatedInitChain) {
const ObjCMethodDecl *InitMethod = 0;
bool isDesignated =
MD->isDesignatedInitializerForTheInterface(&InitMethod);
assert(isDesignated && InitMethod);
(void)isDesignated;
auto superIsNSObject = [&](const ObjCMethodDecl *MD) {
auto IFace = MD->getClassInterface();
if (!IFace)
return false;
auto SuperD = IFace->getSuperClass();
if (!SuperD)
return false;
return SuperD->getIdentifier() ==
NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject);
};
if (!MD->isUnavailable() && !superIsNSObject(MD)) {
Diag(MD->getLocation(),
diag::warn_objc_designated_init_missing_super_call);
Diag(InitMethod->getLocation(),
diag::note_objc_designated_init_marked_here);
}
getCurFunction()->ObjCWarnForNoDesignatedInitChain = false;
}
if (getCurFunction()->ObjCWarnForNoInitDelegation) {
if (!MD->isUnavailable())
Diag(MD->getLocation(), diag::warn_objc_secondary_init_missing_init_call);
getCurFunction()->ObjCWarnForNoInitDelegation = false;
}
} else {
return 0;
}
assert(!getCurFunction()->ObjCShouldCallSuper &&
"This should only be set for ObjC methods, which should have been "
"handled in the block above.");
if (Body) {
if (FD && isa<CXXConstructorDecl>(FD) && isa<CXXTryStmt>(Body))
DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body));
if (getCurFunction()->NeedsScopeChecking() &&
!dcl->isInvalidDecl() &&
!hasAnyUnrecoverableErrorsInThisFunction() &&
!PP.isCodeCompletionEnabled())
DiagnoseInvalidJumps(Body);
if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl)) {
if (!Destructor->getParent()->isDependentType())
CheckDestructor(Destructor);
MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(),
Destructor->getParent());
}
if (PP.getDiagnostics().hasErrorOccurred() ||
PP.getDiagnostics().getSuppressAllDiagnostics()) {
DiscardCleanupsInEvaluationContext();
}
if (!PP.getDiagnostics().hasUncompilableErrorOccurred() &&
!isa<FunctionTemplateDecl>(dcl)) {
ActivePolicy = &WP;
}
if (!IsInstantiation && FD && FD->isConstexpr() && !FD->isInvalidDecl() &&
(!CheckConstexprFunctionDecl(FD) ||
!CheckConstexprFunctionBody(FD, Body)))
FD->setInvalidDecl();
assert(!ExprNeedsCleanups && "Unaccounted cleanups in function");
assert(MaybeODRUseExprs.empty() &&
"Leftover expressions for odr-use checking");
}
if (!IsInstantiation)
PopDeclContext();
PopFunctionScopeInfo(ActivePolicy, dcl);
if (getDiagnostics().hasErrorOccurred()) {
DiscardCleanupsInEvaluationContext();
}
return dcl;
}
void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D,
ParsedAttributes &Attrs) {
if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
D = TD->getTemplatedDecl();
ProcessDeclAttributeList(S, D, Attrs.getList());
if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(D))
if (Method->isStatic())
checkThisInStaticMemberFunctionAttributes(Method);
}
NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
IdentifierInfo &II, Scope *S) {
if (NamedDecl *ExternCPrev = findLocallyScopedExternCDecl(&II)) {
Diag(Loc, diag::warn_use_out_of_scope_declaration) << ExternCPrev;
Diag(ExternCPrev->getLocation(), diag::note_previous_declaration);
return ExternCPrev;
}
unsigned diag_id;
if (II.getName().startswith("__builtin_"))
diag_id = diag::warn_builtin_unknown;
else if (getLangOpts().C99)
diag_id = diag::ext_implicit_function_decl;
else
diag_id = diag::warn_implicit_function_decl;
Diag(Loc, diag_id) << &II;
if (Diags.getDiagnosticLevel(diag_id, Loc) >= DiagnosticsEngine::Error) {
TypoCorrection Corrected;
DeclFilterCCC<FunctionDecl> Validator;
if (S && (Corrected = CorrectTypo(DeclarationNameInfo(&II, Loc),
LookupOrdinaryName, S, 0, Validator)))
diagnoseTypo(Corrected, PDiag(diag::note_function_suggestion),
false);
}
const char *Dummy;
AttributeFactory attrFactory;
DeclSpec DS(attrFactory);
unsigned DiagID;
bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID,
Context.getPrintingPolicy());
(void)Error; assert(!Error && "Error setting up implicit decl!");
SourceLocation NoLoc;
Declarator D(DS, Declarator::BlockContext);
D.AddTypeInfo(DeclaratorChunk::getFunction(false,
false,
NoLoc,
0,
0,
NoLoc,
NoLoc,
0,
true,
NoLoc,
NoLoc,
NoLoc,
NoLoc,
EST_None,
NoLoc,
0,
0,
0,
0,
Loc, Loc, D),
DS.getAttributes(),
SourceLocation());
D.SetIdentifier(&II, Loc);
DeclContext *PrevDC = CurContext;
CurContext = Context.getTranslationUnitDecl();
FunctionDecl *FD = cast<FunctionDecl>(ActOnDeclarator(TUScope, D));
FD->setImplicit();
CurContext = PrevDC;
AddKnownFunctionAttributes(FD);
return FD;
}
void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
if (FD->isInvalidDecl())
return;
if (unsigned BuiltinID = FD->getBuiltinID()) {
unsigned FormatIdx;
bool HasVAListArg;
if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) {
if (!FD->hasAttr<FormatAttr>()) {
const char *fmt = "printf";
unsigned int NumParams = FD->getNumParams();
if (FormatIdx < NumParams && FD->getParamDecl(FormatIdx)->getType()->isObjCObjectPointerType())
fmt = "NSString";
FD->addAttr(FormatAttr::CreateImplicit(Context,
&Context.Idents.get(fmt),
FormatIdx+1,
HasVAListArg ? 0 : FormatIdx+2,
FD->getLocation()));
}
}
if (Context.BuiltinInfo.isScanfLike(BuiltinID, FormatIdx,
HasVAListArg)) {
if (!FD->hasAttr<FormatAttr>())
FD->addAttr(FormatAttr::CreateImplicit(Context,
&Context.Idents.get("scanf"),
FormatIdx+1,
HasVAListArg ? 0 : FormatIdx+2,
FD->getLocation()));
}
if (!getLangOpts().MathErrno &&
Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) {
if (!FD->hasAttr<ConstAttr>())
FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation()));
}
if (Context.BuiltinInfo.isReturnsTwice(BuiltinID) &&
!FD->hasAttr<ReturnsTwiceAttr>())
FD->addAttr(ReturnsTwiceAttr::CreateImplicit(Context,
FD->getLocation()));
if (Context.BuiltinInfo.isNoThrow(BuiltinID) && !FD->hasAttr<NoThrowAttr>())
FD->addAttr(NoThrowAttr::CreateImplicit(Context, FD->getLocation()));
if (Context.BuiltinInfo.isConst(BuiltinID) && !FD->hasAttr<ConstAttr>())
FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation()));
}
IdentifierInfo *Name = FD->getIdentifier();
if (!Name)
return;
if ((!getLangOpts().CPlusPlus &&
FD->getDeclContext()->isTranslationUnit()) ||
(isa<LinkageSpecDecl>(FD->getDeclContext()) &&
cast<LinkageSpecDecl>(FD->getDeclContext())->getLanguage() ==
LinkageSpecDecl::lang_c)) {
} else
return;
if (Name->isStr("asprintf") || Name->isStr("vasprintf")) {
if (!FD->hasAttr<FormatAttr>())
FD->addAttr(FormatAttr::CreateImplicit(Context,
&Context.Idents.get("printf"), 2,
Name->isStr("vasprintf") ? 0 : 3,
FD->getLocation()));
}
if (Name->isStr("__CFStringMakeConstantString")) {
if (!FD->hasAttr<FormatArgAttr>())
FD->addAttr(FormatArgAttr::CreateImplicit(Context, 1,
FD->getLocation()));
}
}
TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
TypeSourceInfo *TInfo) {
assert(D.getIdentifier() && "Wrong callback for declspec without declarator");
assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
if (!TInfo) {
assert(D.isInvalidType() && "no declarator info for valid type");
TInfo = Context.getTrivialTypeSourceInfo(T);
}
TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext,
D.getLocStart(),
D.getIdentifierLoc(),
D.getIdentifier(),
TInfo);
if (D.isInvalidType()) {
NewTD->setInvalidDecl();
return NewTD;
}
if (D.getDeclSpec().isModulePrivateSpecified()) {
if (CurContext->isFunctionOrMethod())
Diag(NewTD->getLocation(), diag::err_module_private_local)
<< 2 << NewTD->getDeclName()
<< SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
<< FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
else
NewTD->setModulePrivate();
}
switch (D.getDeclSpec().getTypeSpecType()) {
case TST_enum:
case TST_struct:
case TST_interface:
case TST_union:
case TST_class: {
TagDecl *tagFromDeclSpec = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
if (tagFromDeclSpec->getIdentifier()) break;
if (tagFromDeclSpec->getTypedefNameForAnonDecl()) break;
assert(tagFromDeclSpec->isThisDeclarationADefinition());
if (!Context.hasSameType(T, Context.getTagDeclType(tagFromDeclSpec)))
break;
if (tagFromDeclSpec->hasLinkageBeenComputed()) {
Diag(D.getIdentifierLoc(), diag::err_typedef_changes_linkage);
SourceLocation tagLoc = D.getDeclSpec().getTypeSpecTypeLoc();
tagLoc = Lexer::getLocForEndOfToken(tagLoc, 0, getSourceManager(),
getLangOpts());
llvm::SmallString<40> textToInsert;
textToInsert += ' ';
textToInsert += D.getIdentifier()->getName();
Diag(tagLoc, diag::note_typedef_changes_linkage)
<< FixItHint::CreateInsertion(tagLoc, textToInsert);
break;
}
tagFromDeclSpec->setTypedefNameForAnonDecl(NewTD);
break;
}
default:
break;
}
return NewTD;
}
bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) {
SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc();
QualType T = TI->getType();
if (T->isDependentType())
return false;
if (const BuiltinType *BT = T->getAs<BuiltinType>())
if (BT->isInteger())
return false;
Diag(UnderlyingLoc, diag::err_enum_invalid_underlying) << T;
return true;
}
bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
QualType EnumUnderlyingTy,
const EnumDecl *Prev) {
bool IsFixed = !EnumUnderlyingTy.isNull();
if (IsScoped != Prev->isScoped()) {
Diag(EnumLoc, diag::err_enum_redeclare_scoped_mismatch)
<< Prev->isScoped();
Diag(Prev->getLocation(), diag::note_previous_declaration);
return true;
}
if (IsFixed && Prev->isFixed()) {
if (!EnumUnderlyingTy->isDependentType() &&
!Prev->getIntegerType()->isDependentType() &&
!Context.hasSameUnqualifiedType(EnumUnderlyingTy,
Prev->getIntegerType())) {
Diag(EnumLoc, diag::err_enum_redeclare_type_mismatch)
<< EnumUnderlyingTy << Prev->getIntegerType();
Diag(Prev->getLocation(), diag::note_previous_declaration)
<< Prev->getIntegerTypeRange();
return true;
}
} else if (IsFixed != Prev->isFixed()) {
Diag(EnumLoc, diag::err_enum_redeclare_fixed_mismatch)
<< Prev->isFixed();
Diag(Prev->getLocation(), diag::note_previous_declaration);
return true;
}
return false;
}
static unsigned getRedeclDiagFromTagKind(TagTypeKind Tag) {
switch (Tag) {
case TTK_Struct: return 0;
case TTK_Interface: return 1;
case TTK_Class: return 2;
default: llvm_unreachable("Invalid tag kind for redecl diagnostic!");
}
}
static bool isClassCompatTagKind(TagTypeKind Tag)
{
return Tag == TTK_Struct || Tag == TTK_Class || Tag == TTK_Interface;
}
bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
TagTypeKind NewTag, bool isDefinition,
SourceLocation NewTagLoc,
const IdentifierInfo &Name) {
TagTypeKind OldTag = Previous->getTagKind();
if (!isDefinition || !isClassCompatTagKind(NewTag))
if (OldTag == NewTag)
return true;
if (isClassCompatTagKind(OldTag) && isClassCompatTagKind(NewTag)) {
bool isTemplate = false;
if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Previous))
isTemplate = Record->getDescribedClassTemplate();
if (!ActiveTemplateInstantiations.empty()) {
Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch)
<< getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name
<< getRedeclDiagFromTagKind(OldTag);
return true;
}
if (isDefinition) {
if (Previous->getDefinition()) {
return true;
}
bool previousMismatch = false;
for (TagDecl::redecl_iterator I(Previous->redecls_begin()),
E(Previous->redecls_end()); I != E; ++I) {
if (I->getTagKind() != NewTag) {
if (!previousMismatch) {
previousMismatch = true;
Diag(NewTagLoc, diag::warn_struct_class_previous_tag_mismatch)
<< getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name
<< getRedeclDiagFromTagKind(I->getTagKind());
}
Diag(I->getInnerLocStart(), diag::note_struct_class_suggestion)
<< getRedeclDiagFromTagKind(NewTag)
<< FixItHint::CreateReplacement(I->getInnerLocStart(),
TypeWithKeyword::getTagTypeKindName(NewTag));
}
}
return true;
}
const TagDecl *Redecl = Previous->getDefinition() ?
Previous->getDefinition() : Previous;
if (Redecl->getTagKind() == NewTag) {
return true;
}
Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch)
<< getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name
<< getRedeclDiagFromTagKind(OldTag);
Diag(Redecl->getLocation(), diag::note_previous_use);
if (Previous->getDefinition()) {
Diag(NewTagLoc, diag::note_struct_class_suggestion)
<< getRedeclDiagFromTagKind(Redecl->getTagKind())
<< FixItHint::CreateReplacement(SourceRange(NewTagLoc),
TypeWithKeyword::getTagTypeKindName(Redecl->getTagKind()));
}
return true;
}
return false;
}
Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
SourceLocation KWLoc, CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
AttributeList *Attr, AccessSpecifier AS,
SourceLocation ModulePrivateLoc,
MultiTemplateParamsArg TemplateParameterLists,
bool &OwnedDecl, bool &IsDependent,
SourceLocation ScopedEnumKWLoc,
bool ScopedEnumUsesClassTag,
TypeResult UnderlyingType,
bool IsTypeSpecifier) {
IdentifierInfo *OrigName = Name;
assert((Name != 0 || TUK == TUK_Definition) &&
"Nameless record must be a definition!");
assert(TemplateParameterLists.size() == 0 || TUK != TUK_Reference);
OwnedDecl = false;
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
bool ScopedEnum = ScopedEnumKWLoc.isValid();
bool isExplicitSpecialization = false;
bool Invalid = false;
if (TemplateParameterLists.size() > 0 ||
(SS.isNotEmpty() && TUK != TUK_Reference)) {
if (TemplateParameterList *TemplateParams =
MatchTemplateParametersToScopeSpecifier(
KWLoc, NameLoc, SS, TemplateParameterLists, TUK == TUK_Friend,
isExplicitSpecialization, Invalid)) {
if (Kind == TTK_Enum) {
Diag(KWLoc, diag::err_enum_template);
return 0;
}
if (TemplateParams->size() > 0) {
if (Invalid)
return 0;
OwnedDecl = false;
DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc,
SS, Name, NameLoc, Attr,
TemplateParams, AS,
ModulePrivateLoc,
TemplateParameterLists.size()-1,
TemplateParameterLists.data());
return Result.get();
} else {
Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams)
<< TypeWithKeyword::getTagTypeKindName(Kind) << Name;
isExplicitSpecialization = true;
}
}
}
llvm::PointerUnion<const Type*, TypeSourceInfo*> EnumUnderlying;
if (Kind == TTK_Enum) {
if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum))
EnumUnderlying = Context.IntTy.getTypePtr();
else if (UnderlyingType.get()) {
TypeSourceInfo *TI = 0;
GetTypeFromParser(UnderlyingType.get(), &TI);
EnumUnderlying = TI;
if (CheckEnumUnderlyingType(TI))
EnumUnderlying = Context.IntTy.getTypePtr();
if (DiagnoseUnexpandedParameterPack(TI->getTypeLoc().getBeginLoc(), TI,
UPPC_FixedUnderlyingType))
EnumUnderlying = Context.IntTy.getTypePtr();
} else if (getLangOpts().MSVCCompat)
EnumUnderlying = Context.IntTy.getTypePtr();
}
DeclContext *SearchDC = CurContext;
DeclContext *DC = CurContext;
bool isStdBadAlloc = false;
RedeclarationKind Redecl = ForRedeclaration;
if (TUK == TUK_Friend || TUK == TUK_Reference)
Redecl = NotForRedeclaration;
LookupResult Previous(*this, Name, NameLoc, LookupTagName, Redecl);
bool FriendSawTagOutsideEnclosingNamespace = false;
if (Name && SS.isNotEmpty()) {
if (SS.isInvalid()) {
Name = 0;
goto CreateNewDecl;
}
if (TUK == TUK_Friend || TUK == TUK_Reference) {
DC = computeDeclContext(SS, false);
if (!DC) {
IsDependent = true;
return 0;
}
} else {
DC = computeDeclContext(SS, true);
if (!DC) {
Diag(SS.getRange().getBegin(), diag::err_dependent_nested_name_spec)
<< SS.getRange();
return 0;
}
}
if (RequireCompleteDeclContext(SS, DC))
return 0;
SearchDC = DC;
LookupQualifiedName(Previous, DC);
if (Previous.isAmbiguous())
return 0;
if (Previous.empty()) {
if (Previous.wasNotFoundInCurrentInstantiation() &&
(TUK == TUK_Reference || TUK == TUK_Friend)) {
IsDependent = true;
return 0;
}
Diag(NameLoc, diag::err_not_tag_in_scope)
<< Kind << Name << DC << SS.getRange();
Name = 0;
Invalid = true;
goto CreateNewDecl;
}
} else if (Name) {
LookupName(Previous, S);
if (Previous.isAmbiguous() &&
(TUK == TUK_Definition || TUK == TUK_Declaration)) {
LookupResult::Filter F = Previous.makeFilter();
while (F.hasNext()) {
NamedDecl *ND = F.next();
if (ND->getDeclContext()->getRedeclContext() != SearchDC)
F.erase();
}
F.done();
}
if (!Previous.empty() && TUK == TUK_Friend) {
DeclContext *EnclosingNS = SearchDC->getEnclosingNamespaceContext();
LookupResult::Filter F = Previous.makeFilter();
while (F.hasNext()) {
NamedDecl *ND = F.next();
DeclContext *DC = ND->getDeclContext()->getRedeclContext();
if (DC->isFileContext() &&
!EnclosingNS->Encloses(ND->getDeclContext())) {
F.erase();
FriendSawTagOutsideEnclosingNamespace = true;
}
}
F.done();
}
if (Previous.isAmbiguous())
return 0;
if (!getLangOpts().CPlusPlus && TUK != TUK_Reference) {
while (isa<RecordDecl>(SearchDC) || isa<EnumDecl>(SearchDC))
SearchDC = SearchDC->getParent();
}
} else if (S->isFunctionPrototypeScope()) {
SearchDC = Context.getTranslationUnitDecl();
}
if (Previous.isSingleResult() &&
Previous.getFoundDecl()->isTemplateParameter()) {
DiagnoseTemplateParameterShadow(NameLoc, Previous.getFoundDecl());
Previous.clear();
}
if (getLangOpts().CPlusPlus && Name && DC && StdNamespace &&
DC->Equals(getStdNamespace()) && Name->isStr("bad_alloc")) {
isStdBadAlloc = true;
if (Previous.empty() && StdBadAlloc) {
Previous.addDecl(getStdBadAlloc());
}
}
if (Name && Previous.empty() &&
(TUK == TUK_Reference || TUK == TUK_Friend)) {
if (Invalid) goto CreateNewDecl;
assert(SS.isEmpty());
if (TUK == TUK_Reference) {
while (!SearchDC->isFileContext() && !SearchDC->isFunctionOrMethod())
SearchDC = SearchDC->getParent();
while (S->isClassScope() ||
(getLangOpts().CPlusPlus &&
S->isFunctionPrototypeScope()) ||
((S->getFlags() & Scope::DeclScope) == 0) ||
(S->getEntity() && S->getEntity()->isTransparentContext()))
S = S->getParent();
} else {
assert(TUK == TUK_Friend);
SearchDC = SearchDC->getEnclosingNamespaceContext();
}
if (getLangOpts().CPlusPlus) {
Previous.setRedeclarationKind(ForRedeclaration);
LookupQualifiedName(Previous, SearchDC);
}
}
if (!Previous.empty()) {
NamedDecl *PrevDecl = Previous.getFoundDecl();
NamedDecl *DirectPrevDecl =
getLangOpts().MSVCCompat ? *Previous.begin() : PrevDecl;
if (getLangOpts().CPlusPlus) {
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(PrevDecl)) {
if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) {
TagDecl *Tag = TT->getDecl();
if (Tag->getDeclName() == Name &&
Tag->getDeclContext()->getRedeclContext()
->Equals(TD->getDeclContext()->getRedeclContext())) {
PrevDecl = Tag;
Previous.clear();
Previous.addDecl(Tag);
Previous.resolveKind();
}
}
}
}
if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
if (TUK == TUK_Reference || TUK == TUK_Friend ||
isDeclInScope(DirectPrevDecl, SearchDC, S,
SS.isNotEmpty() || isExplicitSpecialization)) {
if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind,
TUK == TUK_Definition, KWLoc,
*Name)) {
bool SafeToContinue
= (PrevTagDecl->getTagKind() != TTK_Enum &&
Kind != TTK_Enum);
if (SafeToContinue)
Diag(KWLoc, diag::err_use_with_wrong_tag)
<< Name
<< FixItHint::CreateReplacement(SourceRange(KWLoc),
PrevTagDecl->getKindName());
else
Diag(KWLoc, diag::err_use_with_wrong_tag) << Name;
Diag(PrevTagDecl->getLocation(), diag::note_previous_use);
if (SafeToContinue)
Kind = PrevTagDecl->getTagKind();
else {
Name = 0;
Previous.clear();
Invalid = true;
}
}
if (Kind == TTK_Enum && PrevTagDecl->getTagKind() == TTK_Enum) {
const EnumDecl *PrevEnum = cast<EnumDecl>(PrevTagDecl);
if (TUK == TUK_Reference || TUK == TUK_Friend) {
if (ScopedEnum)
Diag(ScopedEnumKWLoc, diag::err_enum_class_reference)
<< PrevEnum->isScoped()
<< FixItHint::CreateRemoval(ScopedEnumKWLoc);
return PrevTagDecl;
}
QualType EnumUnderlyingTy;
if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast<TypeSourceInfo*>())
EnumUnderlyingTy = TI->getType().getUnqualifiedType();
else if (const Type *T = EnumUnderlying.dyn_cast<const Type*>())
EnumUnderlyingTy = QualType(T, 0);
if (CheckEnumRedeclaration(NameLoc.isValid() ? NameLoc : KWLoc,
ScopedEnum, EnumUnderlyingTy, PrevEnum))
return TUK == TUK_Declaration ? PrevTagDecl : 0;
}
if (TUK == TUK_Declaration && PrevDecl->isCXXClassMember() &&
S->isDeclScope(PrevDecl)) {
Diag(NameLoc, diag::ext_member_redeclared);
Diag(PrevTagDecl->getLocation(), diag::note_previous_declaration);
}
if (!Invalid) {
if (!Attr &&
((TUK == TUK_Reference &&
(!PrevTagDecl->getFriendObjectKind() || getLangOpts().MicrosoftExt))
|| TUK == TUK_Friend))
return PrevTagDecl;
if (TUK == TUK_Definition) {
if (TagDecl *Def = PrevTagDecl->getDefinition()) {
bool IsExplicitSpecializationAfterInstantiation = false;
if (isExplicitSpecialization) {
if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Def))
IsExplicitSpecializationAfterInstantiation =
RD->getTemplateSpecializationKind() !=
TSK_ExplicitSpecialization;
else if (EnumDecl *ED = dyn_cast<EnumDecl>(Def))
IsExplicitSpecializationAfterInstantiation =
ED->getTemplateSpecializationKind() !=
TSK_ExplicitSpecialization;
}
if (!IsExplicitSpecializationAfterInstantiation) {
if (!getLangOpts().CPlusPlus && S->containedInPrototypeScope())
Diag(NameLoc, diag::warn_redefinition_in_param_list) << Name;
else
Diag(NameLoc, diag::err_redefinition) << Name;
Diag(Def->getLocation(), diag::note_previous_definition);
Name = 0;
Previous.clear();
Invalid = true;
}
} else {
const TagType *Tag
= cast<TagType>(Context.getTagDeclType(PrevTagDecl));
if (Tag->isBeingDefined()) {
Diag(NameLoc, diag::err_nested_redefinition) << Name;
Diag(PrevTagDecl->getLocation(),
diag::note_previous_definition);
Name = 0;
Previous.clear();
Invalid = true;
}
}
}
if (TUK == TUK_Friend || TUK == TUK_Reference) {
SearchDC = PrevTagDecl->getDeclContext();
AS = AS_none;
}
}
} else {
Previous.clear();
}
} else {
if ((TUK == TUK_Reference || TUK == TUK_Friend) &&
!Previous.isForRedeclaration()) {
unsigned Kind = 0;
if (isa<TypedefDecl>(PrevDecl)) Kind = 1;
else if (isa<TypeAliasDecl>(PrevDecl)) Kind = 2;
else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 3;
Diag(NameLoc, diag::err_tag_reference_non_tag) << Kind;
Diag(PrevDecl->getLocation(), diag::note_declared_at);
Invalid = true;
} else if (!isDeclInScope(PrevDecl, SearchDC, S,
SS.isNotEmpty() || isExplicitSpecialization)) {
} else if (TUK == TUK_Reference || TUK == TUK_Friend) {
unsigned Kind = 0;
if (isa<TypedefDecl>(PrevDecl)) Kind = 1;
else if (isa<TypeAliasDecl>(PrevDecl)) Kind = 2;
else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 3;
Diag(NameLoc, diag::err_tag_reference_conflict) << Kind;
Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl;
Invalid = true;
} else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(PrevDecl)) {
unsigned Kind = 0;
if (isa<TypeAliasDecl>(PrevDecl)) Kind = 1;
Diag(NameLoc, diag::err_tag_definition_of_typedef)
<< Name << Kind << TND->getUnderlyingType();
Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl;
Invalid = true;
} else {
Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
Name = 0;
Invalid = true;
}
Previous.clear();
}
}
CreateNewDecl:
TagDecl *PrevDecl = 0;
if (Previous.isSingleResult())
PrevDecl = cast<TagDecl>(Previous.getFoundDecl());
SourceLocation Loc = NameLoc.isValid() ? NameLoc : KWLoc;
TagDecl *New;
bool IsForwardReference = false;
if (Kind == TTK_Enum) {
New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name,
cast_or_null<EnumDecl>(PrevDecl), ScopedEnum,
ScopedEnumUsesClassTag, !EnumUnderlying.isNull());
if (TUK != TUK_Definition && !Invalid) {
TagDecl *Def;
if ((getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) &&
cast<EnumDecl>(New)->isFixed()) {
}
else if (PrevDecl && (Def = cast<EnumDecl>(PrevDecl)->getDefinition())) {
Diag(Loc, diag::ext_forward_ref_enum_def)
<< New;
Diag(Def->getLocation(), diag::note_previous_definition);
} else {
unsigned DiagID = diag::ext_forward_ref_enum;
if (getLangOpts().MSVCCompat)
DiagID = diag::ext_ms_forward_ref_enum;
else if (getLangOpts().CPlusPlus)
DiagID = diag::err_forward_ref_enum;
Diag(Loc, DiagID);
if (TUK == TUK_Reference)
IsForwardReference = true;
}
}
if (EnumUnderlying) {
EnumDecl *ED = cast<EnumDecl>(New);
if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast<TypeSourceInfo*>())
ED->setIntegerTypeSourceInfo(TI);
else
ED->setIntegerType(QualType(EnumUnderlying.get<const Type*>(), 0));
ED->setPromotionType(ED->getIntegerType());
}
} else {
if (getLangOpts().CPlusPlus) {
New = CXXRecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name,
cast_or_null<CXXRecordDecl>(PrevDecl));
if (isStdBadAlloc && (!StdBadAlloc || getStdBadAlloc()->isImplicit()))
StdBadAlloc = cast<CXXRecordDecl>(New);
} else
New = RecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name,
cast_or_null<RecordDecl>(PrevDecl));
}
if (getLangOpts().CPlusPlus && IsTypeSpecifier && TUK == TUK_Definition) {
Diag(New->getLocation(), diag::err_type_defined_in_type_specifier)
<< Context.getTagDeclType(New);
Invalid = true;
}
if (SS.isNotEmpty()) {
if (SS.isSet()) {
if (!isExplicitSpecialization &&
(TUK == TUK_Definition || TUK == TUK_Declaration) &&
diagnoseQualifiedDeclaration(SS, DC, OrigName, NameLoc))
Invalid = true;
New->setQualifierInfo(SS.getWithLocInContext(Context));
if (TemplateParameterLists.size() > 0) {
New->setTemplateParameterListsInfo(Context,
TemplateParameterLists.size(),
TemplateParameterLists.data());
}
}
else
Invalid = true;
}
if (RecordDecl *RD = dyn_cast<RecordDecl>(New)) {
if (TUK == TUK_Definition) {
AddAlignmentAttributesForRecord(RD);
AddMsStructLayoutForRecord(RD);
}
}
if (ModulePrivateLoc.isValid()) {
if (isExplicitSpecialization)
Diag(New->getLocation(), diag::err_module_private_specialization)
<< 2
<< FixItHint::CreateRemoval(ModulePrivateLoc);
else if (!SearchDC->isFunctionOrMethod())
New->setModulePrivate();
}
if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous))
Invalid = true;
if (Invalid)
New->setInvalidDecl();
if (Attr)
ProcessDeclAttributeList(S, New, Attr);
if (Name && S->isFunctionPrototypeScope() && !getLangOpts().CPlusPlus)
Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New);
New->setLexicalDeclContext(CurContext);
if (TUK == TUK_Friend)
New->setObjectOfFriendDecl(!FriendSawTagOutsideEnclosingNamespace &&
getLangOpts().MicrosoftExt);
if (!Invalid && SearchDC->isRecord())
SetMemberAccessSpecifier(New, PrevDecl, AS);
if (TUK == TUK_Definition)
New->startDefinition();
if (TUK == TUK_Friend) {
if (PrevDecl)
New->setAccess(PrevDecl->getAccess());
DeclContext *DC = New->getDeclContext()->getRedeclContext();
DC->makeDeclVisibleInContext(New);
if (Name) if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
PushOnScopeChains(New, EnclosingScope, false);
} else if (Name) {
S = getNonFieldDeclScope(S);
PushOnScopeChains(New, S, !IsForwardReference);
if (IsForwardReference)
SearchDC->makeDeclVisibleInContext(New);
} else {
CurContext->addDecl(New);
}
if (IdentifierInfo *II = New->getIdentifier())
if (!New->isInvalidDecl() &&
New->getDeclContext()->getRedeclContext()->isTranslationUnit() &&
II->isStr("FILE"))
Context.setFILEDecl(New);
if (S->isFunctionPrototypeScope() && !getLangOpts().CPlusPlus &&
InFunctionDeclarator && Name)
DeclsInPrototypeScope.push_back(New);
if (PrevDecl)
mergeDeclAttributes(New, PrevDecl);
AddPushedVisibilityAttribute(New);
OwnedDecl = true;
return (Invalid && getLangOpts().CPlusPlus) ? 0 : New;
}
void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) {
AdjustDeclIfTemplate(TagD);
TagDecl *Tag = cast<TagDecl>(TagD);
PushDeclContext(S, Tag);
ActOnDocumentableDecl(TagD);
AddPushedVisibilityAttribute(Tag);
}
Decl *Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) {
assert(isa<ObjCContainerDecl>(IDecl) &&
"ActOnObjCContainerStartDefinition - Not ObjCContainerDecl");
DeclContext *OCD = cast<DeclContext>(IDecl);
assert(getContainingDC(OCD) == CurContext &&
"The next DeclContext should be lexically contained in the current one.");
CurContext = OCD;
return IDecl;
}
void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD,
SourceLocation FinalLoc,
bool IsFinalSpelledSealed,
SourceLocation LBraceLoc) {
AdjustDeclIfTemplate(TagD);
CXXRecordDecl *Record = cast<CXXRecordDecl>(TagD);
FieldCollector->StartClass();
if (!Record->getIdentifier())
return;
if (FinalLoc.isValid())
Record->addAttr(new (Context)
FinalAttr(FinalLoc, Context, IsFinalSpelledSealed));
CXXRecordDecl *InjectedClassName
= CXXRecordDecl::Create(Context, Record->getTagKind(), CurContext,
Record->getLocStart(), Record->getLocation(),
Record->getIdentifier(),
0,
true);
Context.getTypeDeclType(InjectedClassName, Record);
InjectedClassName->setImplicit();
InjectedClassName->setAccess(AS_public);
if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate())
InjectedClassName->setDescribedClassTemplate(Template);
PushOnScopeChains(InjectedClassName, S);
assert(InjectedClassName->isInjectedClassName() &&
"Broken injected-class-name");
}
void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD,
SourceLocation RBraceLoc) {
AdjustDeclIfTemplate(TagD);
TagDecl *Tag = cast<TagDecl>(TagD);
Tag->setRBraceLoc(RBraceLoc);
if (Tag->isBeingDefined()) {
assert(Tag->isInvalidDecl() && "We should already have completed it");
if (RecordDecl *RD = dyn_cast<RecordDecl>(Tag))
RD->completeDefinition();
}
if (isa<CXXRecordDecl>(Tag))
FieldCollector->FinishClass();
PopDeclContext();
if (getCurLexicalContext()->isObjCContainer() &&
Tag->getDeclContext()->isFileContext())
Tag->setTopLevelDeclInObjCContainer();
if (!Tag->isInvalidDecl())
Consumer.HandleTagDeclDefinition(Tag);
}
void Sema::ActOnObjCContainerFinishDefinition() {
PopDeclContext();
}
void Sema::ActOnObjCTemporaryExitContainerContext(DeclContext *DC) {
assert(DC == CurContext && "Mismatch of container contexts");
OriginalLexicalContext = DC;
ActOnObjCContainerFinishDefinition();
}
void Sema::ActOnObjCReenterContainerContext(DeclContext *DC) {
ActOnObjCContainerStartDefinition(cast<Decl>(DC));
OriginalLexicalContext = 0;
}
void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) {
AdjustDeclIfTemplate(TagD);
TagDecl *Tag = cast<TagDecl>(TagD);
Tag->setInvalidDecl();
if (Tag->isBeingDefined()) {
if (RecordDecl *RD = dyn_cast<RecordDecl>(Tag))
RD->completeDefinition();
}
PopDeclContext();
}
ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
IdentifierInfo *FieldName,
QualType FieldTy, bool IsMsStruct,
Expr *BitWidth, bool *ZeroWidth) {
if (ZeroWidth)
*ZeroWidth = true;
if (!FieldTy->isDependentType() && !FieldTy->isIntegralOrEnumerationType()) {
if (RequireCompleteType(FieldLoc, FieldTy, diag::err_field_incomplete))
return ExprError();
if (FieldName)
return Diag(FieldLoc, diag::err_not_integral_type_bitfield)
<< FieldName << FieldTy << BitWidth->getSourceRange();
return Diag(FieldLoc, diag::err_not_integral_type_anon_bitfield)
<< FieldTy << BitWidth->getSourceRange();
} else if (DiagnoseUnexpandedParameterPack(const_cast<Expr *>(BitWidth),
UPPC_BitFieldWidth))
return ExprError();
if (BitWidth->isValueDependent() || BitWidth->isTypeDependent())
return Owned(BitWidth);
llvm::APSInt Value;
ExprResult ICE = VerifyIntegerConstantExpression(BitWidth, &Value);
if (ICE.isInvalid())
return ICE;
BitWidth = ICE.take();
if (Value != 0 && ZeroWidth)
*ZeroWidth = false;
if (Value == 0 && FieldName)
return Diag(FieldLoc, diag::err_bitfield_has_zero_width) << FieldName;
if (Value.isSigned() && Value.isNegative()) {
if (FieldName)
return Diag(FieldLoc, diag::err_bitfield_has_negative_width)
<< FieldName << Value.toString(10);
return Diag(FieldLoc, diag::err_anon_bitfield_has_negative_width)
<< Value.toString(10);
}
if (!FieldTy->isDependentType()) {
uint64_t TypeSize = Context.getTypeSize(FieldTy);
if (Value.getZExtValue() > TypeSize) {
if (!getLangOpts().CPlusPlus || IsMsStruct ||
Context.getTargetInfo().getCXXABI().isMicrosoft()) {
if (FieldName)
return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size)
<< FieldName << (unsigned)Value.getZExtValue()
<< (unsigned)TypeSize;
return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_size)
<< (unsigned)Value.getZExtValue() << (unsigned)TypeSize;
}
if (FieldName)
Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_size)
<< FieldName << (unsigned)Value.getZExtValue()
<< (unsigned)TypeSize;
else
Diag(FieldLoc, diag::warn_anon_bitfield_width_exceeds_type_size)
<< (unsigned)Value.getZExtValue() << (unsigned)TypeSize;
}
}
return Owned(BitWidth);
}
Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart,
Declarator &D, Expr *BitfieldWidth) {
FieldDecl *Res = HandleField(S, cast_or_null<RecordDecl>(TagD),
DeclStart, D, static_cast<Expr*>(BitfieldWidth),
ICIS_NoInit, AS_public);
return Res;
}
FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
SourceLocation DeclStart,
Declarator &D, Expr *BitWidth,
InClassInitStyle InitStyle,
AccessSpecifier AS) {
IdentifierInfo *II = D.getIdentifier();
SourceLocation Loc = DeclStart;
if (II) Loc = D.getIdentifierLoc();
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType T = TInfo->getType();
if (getLangOpts().CPlusPlus) {
CheckExtraCXXDefaultArguments(D);
if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
UPPC_DataMemberType)) {
D.setInvalidType();
T = Context.IntTy;
TInfo = Context.getTrivialTypeSourceInfo(T, Loc);
}
}
if (T.getQualifiers().hasAddressSpace()) {
Diag(Loc, diag::err_field_with_address_space);
D.setInvalidType();
}
if (LangOpts.OpenCL && T->isEventT()) {
Diag(Loc, diag::err_event_t_struct_field);
D.setInvalidType();
}
DiagnoseFunctionSpecifiers(D.getDeclSpec());
if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec())
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_invalid_thread)
<< DeclSpec::getSpecifierName(TSCS);
NamedDecl *PrevDecl = 0;
LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration);
LookupName(Previous, S);
switch (Previous.getResultKind()) {
case LookupResult::Found:
case LookupResult::FoundUnresolvedValue:
PrevDecl = Previous.getAsSingle<NamedDecl>();
break;
case LookupResult::FoundOverloaded:
PrevDecl = Previous.getRepresentativeDecl();
break;
case LookupResult::NotFound:
case LookupResult::NotFoundInCurrentInstantiation:
case LookupResult::Ambiguous:
break;
}
Previous.suppressDiagnostics();
if (PrevDecl && PrevDecl->isTemplateParameter()) {
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
PrevDecl = 0;
}
if (PrevDecl && !isDeclInScope(PrevDecl, Record, S))
PrevDecl = 0;
bool Mutable
= (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable);
SourceLocation TSSL = D.getLocStart();
FieldDecl *NewFD
= CheckFieldDecl(II, T, TInfo, Record, Loc, Mutable, BitWidth, InitStyle,
TSSL, AS, PrevDecl, &D);
if (NewFD->isInvalidDecl())
Record->setInvalidDecl();
if (D.getDeclSpec().isModulePrivateSpecified())
NewFD->setModulePrivate();
if (NewFD->isInvalidDecl() && PrevDecl) {
} else if (II) {
PushOnScopeChains(NewFD, S);
} else
Record->addDecl(NewFD);
return NewFD;
}
FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
TypeSourceInfo *TInfo,
RecordDecl *Record, SourceLocation Loc,
bool Mutable, Expr *BitWidth,
InClassInitStyle InitStyle,
SourceLocation TSSL,
AccessSpecifier AS, NamedDecl *PrevDecl,
Declarator *D) {
IdentifierInfo *II = Name.getAsIdentifierInfo();
bool InvalidDecl = false;
if (D) InvalidDecl = D->isInvalidType();
if (T.isNull()) {
InvalidDecl = true;
T = Context.IntTy;
}
QualType EltTy = Context.getBaseElementType(T);
if (!EltTy->isDependentType()) {
if (RequireCompleteType(Loc, EltTy, diag::err_field_incomplete)) {
Record->setInvalidDecl();
InvalidDecl = true;
} else {
NamedDecl *Def;
EltTy->isIncompleteType(&Def);
if (Def && Def->isInvalidDecl()) {
Record->setInvalidDecl();
InvalidDecl = true;
}
}
}
if (BitWidth && getLangOpts().OpenCL) {
Diag(Loc, diag::err_opencl_bitfields);
InvalidDecl = true;
}
if (!InvalidDecl && T->isVariablyModifiedType()) {
bool SizeIsNegative;
llvm::APSInt Oversized;
TypeSourceInfo *FixedTInfo =
TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context,
SizeIsNegative,
Oversized);
if (FixedTInfo) {
Diag(Loc, diag::warn_illegal_constant_array_size);
TInfo = FixedTInfo;
T = FixedTInfo->getType();
} else {
if (SizeIsNegative)
Diag(Loc, diag::err_typecheck_negative_array_size);
else if (Oversized.getBoolValue())
Diag(Loc, diag::err_array_too_large)
<< Oversized.toString(10);
else
Diag(Loc, diag::err_typecheck_field_variable_size);
InvalidDecl = true;
}
}
if (!InvalidDecl && RequireNonAbstractType(Loc, T,
diag::err_abstract_type_in_decl,
AbstractFieldType))
InvalidDecl = true;
bool ZeroWidth = false;
if (!InvalidDecl && BitWidth) {
BitWidth = VerifyBitField(Loc, II, T, Record->isMsStruct(Context), BitWidth,
&ZeroWidth).take();
if (!BitWidth) {
InvalidDecl = true;
BitWidth = 0;
ZeroWidth = false;
}
}
if (!InvalidDecl && Mutable) {
unsigned DiagID = 0;
if (T->isReferenceType())
DiagID = diag::err_mutable_reference;
else if (T.isConstQualified())
DiagID = diag::err_mutable_const;
if (DiagID) {
SourceLocation ErrLoc = Loc;
if (D && D->getDeclSpec().getStorageClassSpecLoc().isValid())
ErrLoc = D->getDeclSpec().getStorageClassSpecLoc();
Diag(ErrLoc, DiagID);
Mutable = false;
InvalidDecl = true;
}
}
if (InitStyle != ICIS_NoInit)
checkDuplicateDefaultInit(*this, cast<CXXRecordDecl>(Record), Loc);
FieldDecl *NewFD = FieldDecl::Create(Context, Record, TSSL, Loc, II, T, TInfo,
BitWidth, Mutable, InitStyle);
if (InvalidDecl)
NewFD->setInvalidDecl();
if (PrevDecl && !isa<TagDecl>(PrevDecl)) {
Diag(Loc, diag::err_duplicate_member) << II;
Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
NewFD->setInvalidDecl();
}
if (!InvalidDecl && getLangOpts().CPlusPlus) {
if (Record->isUnion()) {
if (const RecordType *RT = EltTy->getAs<RecordType>()) {
CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
if (RDecl->getDefinition()) {
if (CheckNontrivialField(NewFD))
NewFD->setInvalidDecl();
}
}
if (EltTy->isReferenceType()) {
Diag(NewFD->getLocation(), getLangOpts().MicrosoftExt ?
diag::ext_union_member_of_reference_type :
diag::err_union_member_of_reference_type)
<< NewFD->getDeclName() << EltTy;
if (!getLangOpts().MicrosoftExt)
NewFD->setInvalidDecl();
}
}
}
if (D) {
ProcessDeclAttributes(getCurScope(), NewFD, *D);
if (NewFD->hasAttrs())
CheckAlignasUnderalignment(NewFD);
}
if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewFD))
NewFD->setInvalidDecl();
if (T.isObjCGCWeak())
Diag(Loc, diag::warn_attribute_weak_on_field);
NewFD->setAccess(AS);
return NewFD;
}
bool Sema::CheckNontrivialField(FieldDecl *FD) {
assert(FD);
assert(getLangOpts().CPlusPlus && "valid check only for C++");
if (FD->isInvalidDecl() || FD->getType()->isDependentType())
return false;
QualType EltTy = Context.getBaseElementType(FD->getType());
if (const RecordType *RT = EltTy->getAs<RecordType>()) {
CXXRecordDecl *RDecl = cast<CXXRecordDecl>(RT->getDecl());
if (RDecl->getDefinition()) {
CXXSpecialMember member = CXXInvalid;
if (RDecl->hasNonTrivialCopyConstructor())
member = CXXCopyConstructor;
else if (!RDecl->hasTrivialDefaultConstructor())
member = CXXDefaultConstructor;
else if (RDecl->hasNonTrivialCopyAssignment())
member = CXXCopyAssignment;
else if (RDecl->hasNonTrivialDestructor())
member = CXXDestructor;
if (member != CXXInvalid) {
if (!getLangOpts().CPlusPlus11 &&
getLangOpts().ObjCAutoRefCount && RDecl->hasObjectMember()) {
SourceLocation Loc = FD->getLocation();
if (getSourceManager().isInSystemHeader(Loc)) {
if (!FD->hasAttr<UnavailableAttr>())
FD->addAttr(UnavailableAttr::CreateImplicit(Context,
"this system field has retaining ownership",
Loc));
return false;
}
}
Diag(FD->getLocation(), getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_nontrivial_union_or_anon_struct_member :
diag::err_illegal_union_or_anon_struct_member)
<< (int)FD->getParent()->isUnion() << FD->getDeclName() << member;
DiagnoseNontrivial(RDecl, member);
return !getLangOpts().CPlusPlus11;
}
}
}
return false;
}
static ObjCIvarDecl::AccessControl
TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) {
switch (ivarVisibility) {
default: llvm_unreachable("Unknown visitibility kind");
case tok::objc_private: return ObjCIvarDecl::Private;
case tok::objc_public: return ObjCIvarDecl::Public;
case tok::objc_protected: return ObjCIvarDecl::Protected;
case tok::objc_package: return ObjCIvarDecl::Package;
}
}
Decl *Sema::ActOnIvar(Scope *S,
SourceLocation DeclStart,
Declarator &D, Expr *BitfieldWidth,
tok::ObjCKeywordKind Visibility) {
IdentifierInfo *II = D.getIdentifier();
Expr *BitWidth = (Expr*)BitfieldWidth;
SourceLocation Loc = DeclStart;
if (II) Loc = D.getIdentifierLoc();
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType T = TInfo->getType();
if (BitWidth) {
BitWidth = VerifyBitField(Loc, II, T, false, BitWidth).take();
if (!BitWidth)
D.setInvalidType();
} else {
}
if (T->isReferenceType()) {
Diag(Loc, diag::err_ivar_reference_type);
D.setInvalidType();
}
else if (T->isVariablyModifiedType()) {
Diag(Loc, diag::err_typecheck_ivar_variable_size);
D.setInvalidType();
}
ObjCIvarDecl::AccessControl ac =
Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility)
: ObjCIvarDecl::None;
ObjCContainerDecl *EnclosingDecl = cast<ObjCContainerDecl>(CurContext);
if (!EnclosingDecl || EnclosingDecl->isInvalidDecl())
return 0;
ObjCContainerDecl *EnclosingContext;
if (ObjCImplementationDecl *IMPDecl =
dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
if (LangOpts.ObjCRuntime.isFragile()) {
EnclosingContext = IMPDecl->getClassInterface();
assert(EnclosingContext && "Implementation has no class interface!");
}
else
EnclosingContext = EnclosingDecl;
} else {
if (ObjCCategoryDecl *CDecl =
dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) {
if (LangOpts.ObjCRuntime.isFragile() || !CDecl->IsClassExtension()) {
Diag(Loc, diag::err_misplaced_ivar) << CDecl->IsClassExtension();
return 0;
}
}
EnclosingContext = EnclosingDecl;
}
ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, EnclosingContext,
DeclStart, Loc, II, T,
TInfo, ac, (Expr *)BitfieldWidth);
if (II) {
NamedDecl *PrevDecl = LookupSingleName(S, II, Loc, LookupMemberName,
ForRedeclaration);
if (PrevDecl && isDeclInScope(PrevDecl, EnclosingContext, S)
&& !isa<TagDecl>(PrevDecl)) {
Diag(Loc, diag::err_duplicate_member) << II;
Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
NewID->setInvalidDecl();
}
}
ProcessDeclAttributes(S, NewID, D);
if (D.isInvalidType())
NewID->setInvalidDecl();
if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewID))
NewID->setInvalidDecl();
if (D.getDeclSpec().isModulePrivateSpecified())
NewID->setModulePrivate();
if (II) {
S->AddDecl(NewID);
IdResolver.AddDecl(NewID);
}
if (LangOpts.ObjCRuntime.isNonFragile() &&
!NewID->isInvalidDecl() && isa<ObjCInterfaceDecl>(EnclosingDecl))
Diag(Loc, diag::warn_ivars_in_interface);
return NewID;
}
void Sema::ActOnLastBitfield(SourceLocation DeclLoc,
SmallVectorImpl<Decl *> &AllIvarDecls) {
if (LangOpts.ObjCRuntime.isFragile() || AllIvarDecls.empty())
return;
Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1];
ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(ivarDecl);
if (!Ivar->isBitField() || Ivar->getBitWidthValue(Context) == 0)
return;
ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CurContext);
if (!ID) {
if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(CurContext)) {
if (!CD->IsClassExtension())
return;
}
else
return;
}
llvm::APInt Zero(Context.getTypeSize(Context.IntTy), 0);
Expr * BW = IntegerLiteral::Create(Context, Zero, Context.IntTy, DeclLoc);
Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(CurContext),
DeclLoc, DeclLoc, 0,
Context.CharTy,
Context.getTrivialTypeSourceInfo(Context.CharTy,
DeclLoc),
ObjCIvarDecl::Private, BW,
true);
AllIvarDecls.push_back(Ivar);
}
void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
ArrayRef<Decl *> Fields, SourceLocation LBrac,
SourceLocation RBrac, AttributeList *Attr) {
assert(EnclosingDecl && "missing record or interface decl");
if (!Fields.empty() && isa<ObjCContainerDecl>(EnclosingDecl)) {
ObjCContainerDecl *DC = cast<ObjCContainerDecl>(EnclosingDecl);
switch (DC->getKind()) {
default: break;
case Decl::ObjCCategory:
Context.ResetObjCLayout(cast<ObjCCategoryDecl>(DC)->getClassInterface());
break;
case Decl::ObjCImplementation:
Context.
ResetObjCLayout(cast<ObjCImplementationDecl>(DC)->getClassInterface());
break;
}
}
RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl);
unsigned NumNamedMembers = 0;
if (Record) {
for (RecordDecl::decl_iterator i = Record->decls_begin(),
e = Record->decls_end(); i != e; i++) {
if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(*i))
if (IFD->getDeclName())
++NumNamedMembers;
}
}
SmallVector<FieldDecl*, 32> RecFields;
bool ARCErrReported = false;
for (ArrayRef<Decl *>::iterator i = Fields.begin(), end = Fields.end();
i != end; ++i) {
FieldDecl *FD = cast<FieldDecl>(*i);
const Type *FDTy = FD->getType().getTypePtr();
if (!FD->isAnonymousStructOrUnion()) {
RecFields.push_back(FD);
}
if (FD->isInvalidDecl()) {
EnclosingDecl->setInvalidDecl();
continue;
}
if (FDTy->isFunctionType()) {
Diag(FD->getLocation(), diag::err_field_declared_as_function)
<< FD->getDeclName();
FD->setInvalidDecl();
EnclosingDecl->setInvalidDecl();
continue;
} else if (FDTy->isIncompleteArrayType() && Record &&
((i + 1 == Fields.end() && !Record->isUnion()) ||
((getLangOpts().MicrosoftExt ||
getLangOpts().CPlusPlus) &&
(i + 1 == Fields.end() || Record->isUnion())))) {
unsigned DiagID = 0;
if (Record->isUnion())
DiagID = getLangOpts().MicrosoftExt
? diag::ext_flexible_array_union_ms
: getLangOpts().CPlusPlus
? diag::ext_flexible_array_union_gnu
: diag::err_flexible_array_union;
else if (Fields.size() == 1)
DiagID = getLangOpts().MicrosoftExt
? diag::ext_flexible_array_empty_aggregate_ms
: getLangOpts().CPlusPlus
? diag::ext_flexible_array_empty_aggregate_gnu
: NumNamedMembers < 1
? diag::err_flexible_array_empty_aggregate
: 0;
if (DiagID)
Diag(FD->getLocation(), DiagID) << FD->getDeclName()
<< Record->getTagKind();
if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record))
if (RD->getNumVBases() != 0)
Diag(FD->getLocation(), diag::err_flexible_array_virtual_base)
<< FD->getDeclName() << Record->getTagKind();
if (!getLangOpts().C99)
Diag(FD->getLocation(), diag::ext_c99_flexible_array_member)
<< FD->getDeclName() << Record->getTagKind();
QualType BaseElem = Context.getBaseElementType(FD->getType());
if (!BaseElem->isDependentType() && BaseElem.isDestructedType()) {
Diag(FD->getLocation(), diag::err_flexible_array_has_nontrivial_dtor)
<< FD->getDeclName() << FD->getType();
FD->setInvalidDecl();
EnclosingDecl->setInvalidDecl();
continue;
}
if (Record)
Record->setHasFlexibleArrayMember(true);
} else if (!FDTy->isDependentType() &&
RequireCompleteType(FD->getLocation(), FD->getType(),
diag::err_field_incomplete)) {
FD->setInvalidDecl();
EnclosingDecl->setInvalidDecl();
continue;
} else if (const RecordType *FDTTy = FDTy->getAs<RecordType>()) {
if (FDTTy->getDecl()->hasFlexibleArrayMember()) {
if (Record && Record->isUnion()) {
Record->setHasFlexibleArrayMember(true);
} else {
if (i + 1 != Fields.end())
Diag(FD->getLocation(), diag::ext_variable_sized_type_in_struct)
<< FD->getDeclName() << FD->getType();
else {
Diag(FD->getLocation(), diag::ext_flexible_array_in_struct)
<< FD->getDeclName();
if (Record)
Record->setHasFlexibleArrayMember(true);
}
}
}
if (isa<ObjCContainerDecl>(EnclosingDecl) &&
RequireNonAbstractType(FD->getLocation(), FD->getType(),
diag::err_abstract_type_in_decl,
AbstractIvarType)) {
FD->setInvalidDecl();
}
if (Record && FDTTy->getDecl()->hasObjectMember())
Record->setHasObjectMember(true);
if (Record && FDTTy->getDecl()->hasVolatileMember())
Record->setHasVolatileMember(true);
} else if (FDTy->isObjCObjectType()) {
Diag(FD->getLocation(), diag::err_statically_allocated_object)
<< FixItHint::CreateInsertion(FD->getLocation(), "*");
QualType T = Context.getObjCObjectPointerType(FD->getType());
FD->setType(T);
} else if (getLangOpts().ObjCAutoRefCount && Record && !ARCErrReported &&
(!getLangOpts().CPlusPlus || Record->isUnion())) {
QualType T = FD->getType();
Qualifiers::ObjCLifetime lifetime = T.getObjCLifetime();
if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone) {
SourceLocation loc = FD->getLocation();
if (getSourceManager().isInSystemHeader(loc)) {
if (!FD->hasAttr<UnavailableAttr>()) {
FD->addAttr(UnavailableAttr::CreateImplicit(Context,
"this system field has retaining ownership",
loc));
}
} else {
Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag)
<< T->isBlockPointerType() << Record->getTagKind();
}
ARCErrReported = true;
}
} else if (getLangOpts().ObjC1 &&
getLangOpts().getGC() != LangOptions::NonGC &&
Record && !Record->hasObjectMember()) {
if (FD->getType()->isObjCObjectPointerType() ||
FD->getType().isObjCGCStrong())
Record->setHasObjectMember(true);
else if (Context.getAsArrayType(FD->getType())) {
QualType BaseType = Context.getBaseElementType(FD->getType());
if (BaseType->isRecordType() &&
BaseType->getAs<RecordType>()->getDecl()->hasObjectMember())
Record->setHasObjectMember(true);
else if (BaseType->isObjCObjectPointerType() ||
BaseType.isObjCGCStrong())
Record->setHasObjectMember(true);
}
}
if (Record && FD->getType().isVolatileQualified())
Record->setHasVolatileMember(true);
if (FD->getIdentifier())
++NumNamedMembers;
}
if (Record) {
bool Completed = false;
if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record)) {
if (!CXXRecord->isInvalidDecl()) {
for (CXXRecordDecl::conversion_iterator
I = CXXRecord->conversion_begin(),
E = CXXRecord->conversion_end(); I != E; ++I)
I.setAccess((*I)->getAccess());
if (!CXXRecord->isDependentType()) {
if (CXXRecord->hasUserDeclaredDestructor()) {
if (getLangOpts().CPlusPlus11)
AdjustDestructorExceptionSpec(CXXRecord,
CXXRecord->getDestructor());
}
AddImplicitlyDeclaredMembersToClass(CXXRecord);
if (CXXRecord->getNumVBases()) {
CXXFinalOverriderMap FinalOverriders;
CXXRecord->getFinalOverriders(FinalOverriders);
for (CXXFinalOverriderMap::iterator M = FinalOverriders.begin(),
MEnd = FinalOverriders.end();
M != MEnd; ++M) {
for (OverridingMethods::iterator SO = M->second.begin(),
SOEnd = M->second.end();
SO != SOEnd; ++SO) {
assert(SO->second.size() > 0 &&
"Virtual function without overridding functions?");
if (SO->second.size() == 1)
continue;
Diag(Record->getLocation(), diag::err_multiple_final_overriders)
<< (const NamedDecl *)M->first << Record;
Diag(M->first->getLocation(),
diag::note_overridden_virtual_function);
for (OverridingMethods::overriding_iterator
OM = SO->second.begin(),
OMEnd = SO->second.end();
OM != OMEnd; ++OM)
Diag(OM->Method->getLocation(), diag::note_final_overrider)
<< (const NamedDecl *)M->first << OM->Method->getParent();
Record->setInvalidDecl();
}
}
CXXRecord->completeDefinition(&FinalOverriders);
Completed = true;
}
}
}
}
if (!Completed)
Record->completeDefinition();
if (Record->hasAttrs())
CheckAlignasUnderalignment(Record);
bool CheckForZeroSize;
if (!getLangOpts().CPlusPlus) {
CheckForZeroSize = true;
} else {
CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record);
CheckForZeroSize =
CXXRecord->getLexicalDeclContext()->isExternCContext() &&
!CXXRecord->isDependentType() &&
CXXRecord->isCLike();
}
if (CheckForZeroSize) {
bool ZeroSize = true;
bool IsEmpty = true;
unsigned NonBitFields = 0;
for (RecordDecl::field_iterator I = Record->field_begin(),
E = Record->field_end();
(NonBitFields == 0 || ZeroSize) && I != E; ++I) {
IsEmpty = false;
if (I->isUnnamedBitfield()) {
if (I->getBitWidthValue(Context) > 0)
ZeroSize = false;
} else {
++NonBitFields;
QualType FieldType = I->getType();
if (FieldType->isIncompleteType() ||
!Context.getTypeSizeInChars(FieldType).isZero())
ZeroSize = false;
}
}
if (ZeroSize) {
Diag(RecLoc, getLangOpts().CPlusPlus ?
diag::warn_zero_size_struct_union_in_extern_c :
diag::warn_zero_size_struct_union_compat)
<< IsEmpty << Record->isUnion() << (NonBitFields > 1);
}
if (NonBitFields == 0 && !getLangOpts().CPlusPlus) {
Diag(RecLoc, IsEmpty ? diag::ext_empty_struct_union :
diag::ext_no_named_members_in_struct_union)
<< Record->isUnion();
}
}
} else {
ObjCIvarDecl **ClsFields =
reinterpret_cast<ObjCIvarDecl**>(RecFields.data());
if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(EnclosingDecl)) {
ID->setEndOfDefinitionLoc(RBrac);
for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
ClsFields[i]->setLexicalDeclContext(ID);
ID->addDecl(ClsFields[i]);
}
if (ID->getSuperClass())
DiagnoseDuplicateIvars(ID, ID->getSuperClass());
} else if (ObjCImplementationDecl *IMPDecl =
dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
assert(IMPDecl && "ActOnFields - missing ObjCImplementationDecl");
for (unsigned I = 0, N = RecFields.size(); I != N; ++I)
ClsFields[I]->setLexicalDeclContext(IMPDecl);
CheckImplementationIvars(IMPDecl, ClsFields, RecFields.size(), RBrac);
IMPDecl->setIvarLBraceLoc(LBrac);
IMPDecl->setIvarRBraceLoc(RBrac);
} else if (ObjCCategoryDecl *CDecl =
dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) {
ObjCInterfaceDecl *IDecl = CDecl->getClassInterface();
for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
if (IDecl) {
if (const ObjCIvarDecl *ClsIvar =
IDecl->getIvarDecl(ClsFields[i]->getIdentifier())) {
Diag(ClsFields[i]->getLocation(),
diag::err_duplicate_ivar_declaration);
Diag(ClsIvar->getLocation(), diag::note_previous_definition);
continue;
}
for (ObjCInterfaceDecl::known_extensions_iterator
Ext = IDecl->known_extensions_begin(),
ExtEnd = IDecl->known_extensions_end();
Ext != ExtEnd; ++Ext) {
if (const ObjCIvarDecl *ClsExtIvar
= Ext->getIvarDecl(ClsFields[i]->getIdentifier())) {
Diag(ClsFields[i]->getLocation(),
diag::err_duplicate_ivar_declaration);
Diag(ClsExtIvar->getLocation(), diag::note_previous_definition);
continue;
}
}
}
ClsFields[i]->setLexicalDeclContext(CDecl);
CDecl->addDecl(ClsFields[i]);
}
CDecl->setIvarLBraceLoc(LBrac);
CDecl->setIvarRBraceLoc(RBrac);
}
}
if (Attr)
ProcessDeclAttributeList(S, Record, Attr);
}
static bool isRepresentableIntegerValue(ASTContext &Context,
llvm::APSInt &Value,
QualType T) {
assert(T->isIntegralType(Context) && "Integral type required!");
unsigned BitWidth = Context.getIntWidth(T);
if (Value.isUnsigned() || Value.isNonNegative()) {
if (T->isSignedIntegerOrEnumerationType())
--BitWidth;
return Value.getActiveBits() <= BitWidth;
}
return Value.getMinSignedBits() <= BitWidth;
}
static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) {
assert(T->isIntegralType(Context) && "Integral type required!");
const unsigned NumTypes = 4;
QualType SignedIntegralTypes[NumTypes] = {
Context.ShortTy, Context.IntTy, Context.LongTy, Context.LongLongTy
};
QualType UnsignedIntegralTypes[NumTypes] = {
Context.UnsignedShortTy, Context.UnsignedIntTy, Context.UnsignedLongTy,
Context.UnsignedLongLongTy
};
unsigned BitWidth = Context.getTypeSize(T);
QualType *Types = T->isSignedIntegerOrEnumerationType()? SignedIntegralTypes
: UnsignedIntegralTypes;
for (unsigned I = 0; I != NumTypes; ++I)
if (Context.getTypeSize(Types[I]) > BitWidth)
return Types[I];
return QualType();
}
EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
EnumConstantDecl *LastEnumConst,
SourceLocation IdLoc,
IdentifierInfo *Id,
Expr *Val) {
unsigned IntWidth = Context.getTargetInfo().getIntWidth();
llvm::APSInt EnumVal(IntWidth);
QualType EltTy;
if (Val && DiagnoseUnexpandedParameterPack(Val, UPPC_EnumeratorValue))
Val = 0;
if (Val)
Val = DefaultLvalueConversion(Val).take();
if (Val) {
if (Enum->isDependentType() || Val->isTypeDependent())
EltTy = Context.DependentTy;
else {
SourceLocation ExpLoc;
if (getLangOpts().CPlusPlus11 && Enum->isFixed() &&
!getLangOpts().MSVCCompat) {
EltTy = Enum->getIntegerType();
ExprResult Converted =
CheckConvertedConstantExpression(Val, EltTy, EnumVal,
CCEK_Enumerator);
if (Converted.isInvalid())
Val = 0;
else
Val = Converted.take();
} else if (!Val->isValueDependent() &&
!(Val = VerifyIntegerConstantExpression(Val,
&EnumVal).take())) {
} else {
if (Enum->isFixed()) {
EltTy = Enum->getIntegerType();
if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) {
if (getLangOpts().MSVCCompat) {
Diag(IdLoc, diag::ext_enumerator_too_large) << EltTy;
Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take();
} else
Diag(IdLoc, diag::err_enumerator_too_large) << EltTy;
} else
Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take();
} else if (getLangOpts().CPlusPlus) {
EltTy = Val->getType();
} else {
if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy))
Diag(IdLoc, diag::ext_enum_value_not_int)
<< EnumVal.toString(10) << Val->getSourceRange()
<< (EnumVal.isUnsigned() || EnumVal.isNonNegative());
else if (!Context.hasSameType(Val->getType(), Context.IntTy)) {
Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).take();
}
EltTy = Val->getType();
}
}
}
}
if (!Val) {
if (Enum->isDependentType())
EltTy = Context.DependentTy;
else if (!LastEnumConst) {
if (Enum->isFixed()) {
EltTy = Enum->getIntegerType();
}
else {
EltTy = Context.IntTy;
}
} else {
EnumVal = LastEnumConst->getInitVal();
++EnumVal;
EltTy = LastEnumConst->getType();
if (EnumVal < LastEnumConst->getInitVal()) {
QualType T = getNextLargerIntegralType(Context, EltTy);
if (T.isNull() || Enum->isFixed()) {
EnumVal = LastEnumConst->getInitVal();
EnumVal = EnumVal.zext(EnumVal.getBitWidth() * 2);
++EnumVal;
if (Enum->isFixed())
Diag(IdLoc, diag::err_enumerator_wrapped)
<< EnumVal.toString(10)
<< EltTy;
else
Diag(IdLoc, diag::warn_enumerator_too_large)
<< EnumVal.toString(10);
} else {
EltTy = T;
}
EnumVal = LastEnumConst->getInitVal();
EnumVal.setIsSigned(EltTy->isSignedIntegerOrEnumerationType());
EnumVal = EnumVal.zextOrTrunc(Context.getIntWidth(EltTy));
++EnumVal;
if (!getLangOpts().CPlusPlus && !T.isNull())
Diag(IdLoc, diag::warn_enum_value_overflow);
} else if (!getLangOpts().CPlusPlus &&
!isRepresentableIntegerValue(Context, EnumVal, EltTy)) {
Diag(IdLoc, diag::ext_enum_value_not_int)
<< EnumVal.toString(10) << 1;
}
}
}
if (!EltTy->isDependentType()) {
EnumVal = EnumVal.extOrTrunc(Context.getIntWidth(EltTy));
EnumVal.setIsSigned(EltTy->isSignedIntegerOrEnumerationType());
}
return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy,
Val, EnumVal);
}
Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
SourceLocation IdLoc, IdentifierInfo *Id,
AttributeList *Attr,
SourceLocation EqualLoc, Expr *Val) {
EnumDecl *TheEnumDecl = cast<EnumDecl>(theEnumDecl);
EnumConstantDecl *LastEnumConst =
cast_or_null<EnumConstantDecl>(lastEnumConst);
S = getNonFieldDeclScope(S);
NamedDecl *PrevDecl = LookupSingleName(S, Id, IdLoc, LookupOrdinaryName,
ForRedeclaration);
if (PrevDecl && PrevDecl->isTemplateParameter()) {
DiagnoseTemplateParameterShadow(IdLoc, PrevDecl);
PrevDecl = 0;
}
if (PrevDecl) {
assert((getLangOpts().CPlusPlus || !isa<TagDecl>(PrevDecl)) &&
"Received TagDecl when not in C++!");
if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S)) {
if (isa<EnumConstantDecl>(PrevDecl))
Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id;
else
Diag(IdLoc, diag::err_redefinition) << Id;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
return 0;
}
}
if (CXXRecordDecl *Record
= dyn_cast<CXXRecordDecl>(
TheEnumDecl->getDeclContext()->getRedeclContext()))
if (!TheEnumDecl->isScoped() &&
Record->getIdentifier() && Record->getIdentifier() == Id)
Diag(IdLoc, diag::err_member_name_of_class) << Id;
EnumConstantDecl *New =
CheckEnumConstant(TheEnumDecl, LastEnumConst, IdLoc, Id, Val);
if (New) {
if (Attr) ProcessDeclAttributeList(S, New, Attr);
New->setAccess(TheEnumDecl->getAccess());
PushOnScopeChains(New, S);
}
ActOnDocumentableDecl(New);
return New;
}
static bool ValidDuplicateEnum(EnumConstantDecl *ECD, EnumDecl *Enum) {
Expr *InitExpr = ECD->getInitExpr();
if (!InitExpr)
return true;
InitExpr = InitExpr->IgnoreImpCasts();
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr)) {
if (!BO->isAdditiveOp())
return true;
IntegerLiteral *IL = dyn_cast<IntegerLiteral>(BO->getRHS());
if (!IL)
return true;
if (IL->getValue() != 1)
return true;
InitExpr = BO->getLHS();
}
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InitExpr);
if (!DRE)
return true;
EnumConstantDecl *EnumConstant = dyn_cast<EnumConstantDecl>(DRE->getDecl());
if (!EnumConstant)
return true;
if (cast<EnumDecl>(TagDecl::castFromDeclContext(ECD->getDeclContext())) !=
Enum)
return true;
return false;
}
struct DupKey {
int64_t val;
bool isTombstoneOrEmptyKey;
DupKey(int64_t val, bool isTombstoneOrEmptyKey)
: val(val), isTombstoneOrEmptyKey(isTombstoneOrEmptyKey) {}
};
static DupKey GetDupKey(const llvm::APSInt& Val) {
return DupKey(Val.isSigned() ? Val.getSExtValue() : Val.getZExtValue(),
false);
}
struct DenseMapInfoDupKey {
static DupKey getEmptyKey() { return DupKey(0, true); }
static DupKey getTombstoneKey() { return DupKey(1, true); }
static unsigned getHashValue(const DupKey Key) {
return (unsigned)(Key.val * 37);
}
static bool isEqual(const DupKey& LHS, const DupKey& RHS) {
return LHS.isTombstoneOrEmptyKey == RHS.isTombstoneOrEmptyKey &&
LHS.val == RHS.val;
}
};
static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements,
EnumDecl *Enum,
QualType EnumType) {
if (S.Diags.getDiagnosticLevel(diag::warn_duplicate_enum_values,
Enum->getLocation()) ==
DiagnosticsEngine::Ignored)
return;
if (!Enum->getIdentifier())
return;
if (Enum->getNumPositiveBits() > 63 || Enum->getNumNegativeBits() > 64)
return;
typedef SmallVector<EnumConstantDecl *, 3> ECDVector;
typedef SmallVector<ECDVector *, 3> DuplicatesVector;
typedef llvm::PointerUnion<EnumConstantDecl*, ECDVector*> DeclOrVector;
typedef llvm::DenseMap<DupKey, DeclOrVector, DenseMapInfoDupKey>
ValueToVectorMap;
DuplicatesVector DupVector;
ValueToVectorMap EnumMap;
for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elements[i]);
if (!ECD) {
return;
}
if (ECD->getInitExpr())
continue;
DupKey Key = GetDupKey(ECD->getInitVal());
DeclOrVector &Entry = EnumMap[Key];
if (Entry.isNull())
Entry = ECD;
}
for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
EnumConstantDecl *ECD = cast<EnumConstantDecl>(Elements[i]);
if (!ValidDuplicateEnum(ECD, Enum))
continue;
DupKey Key = GetDupKey(ECD->getInitVal());
DeclOrVector& Entry = EnumMap[Key];
if (Entry.isNull())
continue;
if (EnumConstantDecl *D = Entry.dyn_cast<EnumConstantDecl*>()) {
if (D == ECD)
continue;
ECDVector *Vec = new ECDVector();
Vec->push_back(D);
Vec->push_back(ECD);
Entry = Vec;
DupVector.push_back(Vec);
continue;
}
ECDVector *Vec = Entry.get<ECDVector*>();
if (*Vec->begin() == ECD)
continue;
Vec->push_back(ECD);
}
for (DuplicatesVector::iterator DupVectorIter = DupVector.begin(),
DupVectorEnd = DupVector.end();
DupVectorIter != DupVectorEnd; ++DupVectorIter) {
ECDVector *Vec = *DupVectorIter;
assert(Vec->size() > 1 && "ECDVector should have at least 2 elements.");
ECDVector::iterator I = Vec->begin();
S.Diag((*I)->getLocation(), diag::warn_duplicate_enum_values)
<< (*I)->getName() << (*I)->getInitVal().toString(10)
<< (*I)->getSourceRange();
++I;
for (ECDVector::iterator E = Vec->end(); I != E; ++I)
S.Diag((*I)->getLocation(), diag::note_duplicate_element)
<< (*I)->getName() << (*I)->getInitVal().toString(10)
<< (*I)->getSourceRange();
delete Vec;
}
}
void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
SourceLocation RBraceLoc, Decl *EnumDeclX,
ArrayRef<Decl *> Elements,
Scope *S, AttributeList *Attr) {
EnumDecl *Enum = cast<EnumDecl>(EnumDeclX);
QualType EnumType = Context.getTypeDeclType(Enum);
if (Attr)
ProcessDeclAttributeList(S, Enum, Attr);
if (Enum->isDependentType()) {
for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
EnumConstantDecl *ECD =
cast_or_null<EnumConstantDecl>(Elements[i]);
if (!ECD) continue;
ECD->setType(EnumType);
}
Enum->completeDefinition(Context.DependentTy, Context.DependentTy, 0, 0);
return;
}
unsigned IntWidth = Context.getTargetInfo().getIntWidth();
unsigned CharWidth = Context.getTargetInfo().getCharWidth();
unsigned ShortWidth = Context.getTargetInfo().getShortWidth();
unsigned NumNegativeBits = 0;
unsigned NumPositiveBits = 0;
bool AllElementsInt = true;
for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
EnumConstantDecl *ECD =
cast_or_null<EnumConstantDecl>(Elements[i]);
if (!ECD) continue;
const llvm::APSInt &InitVal = ECD->getInitVal();
if (InitVal.isUnsigned() || InitVal.isNonNegative())
NumPositiveBits = std::max(NumPositiveBits,
(unsigned)InitVal.getActiveBits());
else
NumNegativeBits = std::max(NumNegativeBits,
(unsigned)InitVal.getMinSignedBits());
if (AllElementsInt)
AllElementsInt = ECD->getType() == Context.IntTy;
}
QualType BestType;
unsigned BestWidth;
QualType BestPromotionType;
bool Packed = Enum->hasAttr<PackedAttr>();
if (LangOpts.ShortEnums)
Packed = true;
if (Enum->isFixed()) {
BestType = Enum->getIntegerType();
if (BestType->isPromotableIntegerType())
BestPromotionType = Context.getPromotedIntegerType(BestType);
else
BestPromotionType = BestType;
BestWidth = CharWidth;
}
else if (NumNegativeBits) {
if (Packed && NumNegativeBits <= CharWidth && NumPositiveBits < CharWidth) {
BestType = Context.SignedCharTy;
BestWidth = CharWidth;
} else if (Packed && NumNegativeBits <= ShortWidth &&
NumPositiveBits < ShortWidth) {
BestType = Context.ShortTy;
BestWidth = ShortWidth;
} else if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) {
BestType = Context.IntTy;
BestWidth = IntWidth;
} else {
BestWidth = Context.getTargetInfo().getLongWidth();
if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth) {
BestType = Context.LongTy;
} else {
BestWidth = Context.getTargetInfo().getLongLongWidth();
if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth)
Diag(Enum->getLocation(), diag::warn_enum_too_large);
BestType = Context.LongLongTy;
}
}
BestPromotionType = (BestWidth <= IntWidth ? Context.IntTy : BestType);
} else {
if (Packed && NumPositiveBits <= CharWidth) {
BestType = Context.UnsignedCharTy;
BestPromotionType = Context.IntTy;
BestWidth = CharWidth;
} else if (Packed && NumPositiveBits <= ShortWidth) {
BestType = Context.UnsignedShortTy;
BestPromotionType = Context.IntTy;
BestWidth = ShortWidth;
} else if (NumPositiveBits <= IntWidth) {
BestType = Context.UnsignedIntTy;
BestWidth = IntWidth;
BestPromotionType
= (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus)
? Context.UnsignedIntTy : Context.IntTy;
} else if (NumPositiveBits <=
(BestWidth = Context.getTargetInfo().getLongWidth())) {
BestType = Context.UnsignedLongTy;
BestPromotionType
= (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus)
? Context.UnsignedLongTy : Context.LongTy;
} else {
BestWidth = Context.getTargetInfo().getLongLongWidth();
assert(NumPositiveBits <= BestWidth &&
"How could an initializer get larger than ULL?");
BestType = Context.UnsignedLongLongTy;
BestPromotionType
= (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus)
? Context.UnsignedLongLongTy : Context.LongLongTy;
}
}
for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elements[i]);
if (!ECD) continue;
llvm::APSInt InitVal = ECD->getInitVal();
QualType NewTy;
unsigned NewWidth;
bool NewSign;
if (!getLangOpts().CPlusPlus &&
!Enum->isFixed() &&
isRepresentableIntegerValue(Context, InitVal, Context.IntTy)) {
NewTy = Context.IntTy;
NewWidth = IntWidth;
NewSign = true;
} else if (ECD->getType() == BestType) {
if (getLangOpts().CPlusPlus)
ECD->setType(EnumType);
continue;
} else {
NewTy = BestType;
NewWidth = BestWidth;
NewSign = BestType->isSignedIntegerOrEnumerationType();
}
InitVal = InitVal.extOrTrunc(NewWidth);
InitVal.setIsSigned(NewSign);
ECD->setInitVal(InitVal);
if (ECD->getInitExpr() &&
!Context.hasSameType(NewTy, ECD->getInitExpr()->getType()))
ECD->setInitExpr(ImplicitCastExpr::Create(Context, NewTy,
CK_IntegralCast,
ECD->getInitExpr(),
0,
VK_RValue));
if (getLangOpts().CPlusPlus)
ECD->setType(EnumType);
else
ECD->setType(NewTy);
}
Enum->completeDefinition(BestType, BestPromotionType,
NumPositiveBits, NumNegativeBits);
if (InFunctionDeclarator)
DeclsInPrototypeScope.push_back(Enum);
CheckForDuplicateEnumValues(*this, Elements, Enum, EnumType);
if (Enum->hasAttrs())
CheckAlignasUnderalignment(Enum);
}
Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr,
SourceLocation StartLoc,
SourceLocation EndLoc) {
StringLiteral *AsmString = cast<StringLiteral>(expr);
FileScopeAsmDecl *New = FileScopeAsmDecl::Create(Context, CurContext,
AsmString, StartLoc,
EndLoc);
CurContext->addDecl(New);
return New;
}
DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
SourceLocation ImportLoc,
ModuleIdPath Path) {
Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
Module::AllVisible,
false);
if (!Mod)
return true;
if (Mod->getTopLevelModuleName() == getLangOpts().CurrentModule)
Diag(ImportLoc, diag::err_module_self_import)
<< Mod->getFullModuleName() << getLangOpts().CurrentModule;
else if (Mod->getTopLevelModuleName() == getLangOpts().ImplementationOfModule)
Diag(ImportLoc, diag::err_module_import_in_implementation)
<< Mod->getFullModuleName() << getLangOpts().ImplementationOfModule;
SmallVector<SourceLocation, 2> IdentifierLocs;
Module *ModCheck = Mod;
for (unsigned I = 0, N = Path.size(); I != N; ++I) {
if (!ModCheck)
break;
ModCheck = ModCheck->Parent;
IdentifierLocs.push_back(Path[I].second);
}
ImportDecl *Import = ImportDecl::Create(Context,
Context.getTranslationUnitDecl(),
AtLoc.isValid()? AtLoc : ImportLoc,
Mod, IdentifierLocs);
Context.getTranslationUnitDecl()->addDecl(Import);
return Import;
}
void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
PP.getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc,
true);
}
void Sema::createImplicitModuleImport(SourceLocation Loc, Module *Mod) {
TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU,
Loc, Mod, Loc);
TU->addDecl(ImportD);
Consumer.HandleImplicitImportDecl(ImportD);
PP.getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc,
false);
}
void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
IdentifierInfo* AliasName,
SourceLocation PragmaLoc,
SourceLocation NameLoc,
SourceLocation AliasNameLoc) {
Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc,
LookupOrdinaryName);
AsmLabelAttr *Attr = ::new (Context) AsmLabelAttr(AliasNameLoc, Context,
AliasName->getName(), 0);
if (PrevDecl)
PrevDecl->addAttr(Attr);
else
(void)ExtnameUndeclaredIdentifiers.insert(
std::pair<IdentifierInfo*,AsmLabelAttr*>(Name, Attr));
}
void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
SourceLocation PragmaLoc,
SourceLocation NameLoc) {
Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName);
if (PrevDecl) {
PrevDecl->addAttr(WeakAttr::CreateImplicit(Context, PragmaLoc));
} else {
(void)WeakUndeclaredIdentifiers.insert(
std::pair<IdentifierInfo*,WeakInfo>
(Name, WeakInfo((IdentifierInfo*)0, NameLoc)));
}
}
void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name,
IdentifierInfo* AliasName,
SourceLocation PragmaLoc,
SourceLocation NameLoc,
SourceLocation AliasNameLoc) {
Decl *PrevDecl = LookupSingleName(TUScope, AliasName, AliasNameLoc,
LookupOrdinaryName);
WeakInfo W = WeakInfo(Name, NameLoc);
if (PrevDecl) {
if (!PrevDecl->hasAttr<AliasAttr>())
if (NamedDecl *ND = dyn_cast<NamedDecl>(PrevDecl))
DeclApplyPragmaWeak(TUScope, ND, W);
} else {
(void)WeakUndeclaredIdentifiers.insert(
std::pair<IdentifierInfo*,WeakInfo>(AliasName, W));
}
}
Decl *Sema::getObjCDeclContext() const {
return (dyn_cast_or_null<ObjCContainerDecl>(CurContext));
}
AvailabilityResult Sema::getCurContextAvailability() const {
const Decl *D = cast<Decl>(getCurObjCLexicalContext());
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
AvailabilityResult R = MD->getAvailability();
if (R != AR_Available)
return R;
D = MD->getClassInterface();
}
else if (const ObjCImplementationDecl *ID =
dyn_cast<ObjCImplementationDecl>(D)) {
D = ID->getClassInterface();
}
return D->getAvailability();
}