Extract code dealing with variable declarator into a separate function.
No functionality change. llvm-svn: 62300
This commit is contained in:
parent
d243c0e3d9
commit
9b7714d909
|
@ -277,9 +277,12 @@ public:
|
||||||
}
|
}
|
||||||
DeclTy *ActOnDeclarator(Scope *S, Declarator &D, DeclTy *LastInGroup,
|
DeclTy *ActOnDeclarator(Scope *S, Declarator &D, DeclTy *LastInGroup,
|
||||||
bool IsFunctionDefinition);
|
bool IsFunctionDefinition);
|
||||||
|
ScopedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||||
|
QualType R, ScopedDecl* LastDeclarator,
|
||||||
|
Decl* PrevDecl, bool& InvalidDecl);
|
||||||
ScopedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
ScopedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||||
QualType R, ScopedDecl *LastDeclarator,
|
QualType R, ScopedDecl *LastDeclarator,
|
||||||
Decl* PreDecl, bool IsFunctionDefinition,
|
Decl* PrevDecl, bool IsFunctionDefinition,
|
||||||
bool& InvalidDecl);
|
bool& InvalidDecl);
|
||||||
virtual DeclTy *ActOnParamDeclarator(Scope *S, Declarator &D);
|
virtual DeclTy *ActOnParamDeclarator(Scope *S, Declarator &D);
|
||||||
virtual void ActOnParamDefaultArgument(DeclTy *param,
|
virtual void ActOnParamDefaultArgument(DeclTy *param,
|
||||||
|
|
|
@ -1328,105 +1328,8 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl,
|
||||||
New = ActOnFunctionDeclarator(S, D, DC, R, LastDeclarator, PrevDecl,
|
New = ActOnFunctionDeclarator(S, D, DC, R, LastDeclarator, PrevDecl,
|
||||||
IsFunctionDefinition, InvalidDecl);
|
IsFunctionDefinition, InvalidDecl);
|
||||||
} else {
|
} else {
|
||||||
// Check that there are no default arguments (C++ only).
|
New = ActOnVariableDeclarator(S, D, DC, R, LastDeclarator, PrevDecl,
|
||||||
if (getLangOptions().CPlusPlus)
|
InvalidDecl);
|
||||||
CheckExtraCXXDefaultArguments(D);
|
|
||||||
|
|
||||||
if (R.getTypePtr()->isObjCInterfaceType()) {
|
|
||||||
Diag(D.getIdentifierLoc(), diag::err_statically_allocated_object)
|
|
||||||
<< D.getIdentifier();
|
|
||||||
InvalidDecl = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
VarDecl *NewVD;
|
|
||||||
VarDecl::StorageClass SC;
|
|
||||||
switch (D.getDeclSpec().getStorageClassSpec()) {
|
|
||||||
default: assert(0 && "Unknown storage class!");
|
|
||||||
case DeclSpec::SCS_unspecified: SC = VarDecl::None; break;
|
|
||||||
case DeclSpec::SCS_extern: SC = VarDecl::Extern; break;
|
|
||||||
case DeclSpec::SCS_static: SC = VarDecl::Static; break;
|
|
||||||
case DeclSpec::SCS_auto: SC = VarDecl::Auto; break;
|
|
||||||
case DeclSpec::SCS_register: SC = VarDecl::Register; break;
|
|
||||||
case DeclSpec::SCS_private_extern: SC = VarDecl::PrivateExtern; break;
|
|
||||||
case DeclSpec::SCS_mutable:
|
|
||||||
// mutable can only appear on non-static class members, so it's always
|
|
||||||
// an error here
|
|
||||||
Diag(D.getIdentifierLoc(), diag::err_mutable_nonmember);
|
|
||||||
InvalidDecl = true;
|
|
||||||
SC = VarDecl::None;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
IdentifierInfo *II = Name.getAsIdentifierInfo();
|
|
||||||
if (!II) {
|
|
||||||
Diag(D.getIdentifierLoc(), diag::err_bad_variable_name)
|
|
||||||
<< Name.getAsString();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DC->isRecord()) {
|
|
||||||
// This is a static data member for a C++ class.
|
|
||||||
NewVD = CXXClassVarDecl::Create(Context, cast<CXXRecordDecl>(DC),
|
|
||||||
D.getIdentifierLoc(), II,
|
|
||||||
R, LastDeclarator);
|
|
||||||
} else {
|
|
||||||
bool ThreadSpecified = D.getDeclSpec().isThreadSpecified();
|
|
||||||
if (S->getFnParent() == 0) {
|
|
||||||
// C99 6.9p2: The storage-class specifiers auto and register shall not
|
|
||||||
// appear in the declaration specifiers in an external declaration.
|
|
||||||
if (SC == VarDecl::Auto || SC == VarDecl::Register) {
|
|
||||||
Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope);
|
|
||||||
InvalidDecl = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
|
|
||||||
II, R, SC, LastDeclarator,
|
|
||||||
// FIXME: Move to DeclGroup...
|
|
||||||
D.getDeclSpec().getSourceRange().getBegin());
|
|
||||||
NewVD->setThreadSpecified(ThreadSpecified);
|
|
||||||
}
|
|
||||||
// Handle attributes prior to checking for duplicates in MergeVarDecl
|
|
||||||
ProcessDeclAttributes(NewVD, D);
|
|
||||||
|
|
||||||
// Handle GNU asm-label extension (encoded as an attribute).
|
|
||||||
if (Expr *E = (Expr*) D.getAsmLabel()) {
|
|
||||||
// The parser guarantees this is a string.
|
|
||||||
StringLiteral *SE = cast<StringLiteral>(E);
|
|
||||||
NewVD->addAttr(new AsmLabelAttr(std::string(SE->getStrData(),
|
|
||||||
SE->getByteLength())));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit an error if an address space was applied to decl with local storage.
|
|
||||||
// This includes arrays of objects with address space qualifiers, but not
|
|
||||||
// automatic variables that point to other address spaces.
|
|
||||||
// ISO/IEC TR 18037 S5.1.2
|
|
||||||
if (NewVD->hasLocalStorage() && (NewVD->getType().getAddressSpace() != 0)) {
|
|
||||||
Diag(D.getIdentifierLoc(), diag::err_as_qualified_auto_decl);
|
|
||||||
InvalidDecl = true;
|
|
||||||
}
|
|
||||||
// Merge the decl with the existing one if appropriate. If the decl is
|
|
||||||
// in an outer scope, it isn't the same thing.
|
|
||||||
if (PrevDecl && isDeclInScope(PrevDecl, DC, S)) {
|
|
||||||
if (isa<FieldDecl>(PrevDecl) && D.getCXXScopeSpec().isSet()) {
|
|
||||||
// The user tried to define a non-static data member
|
|
||||||
// out-of-line (C++ [dcl.meaning]p1).
|
|
||||||
Diag(NewVD->getLocation(), diag::err_nonstatic_member_out_of_line)
|
|
||||||
<< D.getCXXScopeSpec().getRange();
|
|
||||||
NewVD->Destroy(Context);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
NewVD = MergeVarDecl(NewVD, PrevDecl);
|
|
||||||
if (NewVD == 0) return 0;
|
|
||||||
|
|
||||||
if (D.getCXXScopeSpec().isSet()) {
|
|
||||||
// No previous declaration in the qualifying scope.
|
|
||||||
Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member)
|
|
||||||
<< Name << D.getCXXScopeSpec().getRange();
|
|
||||||
InvalidDecl = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
New = NewVD;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New == 0)
|
if (New == 0)
|
||||||
|
@ -1446,6 +1349,113 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl,
|
||||||
return New;
|
return New;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScopedDecl*
|
||||||
|
Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||||
|
QualType R, ScopedDecl* LastDeclarator,
|
||||||
|
Decl* PrevDecl, bool& InvalidDecl) {
|
||||||
|
DeclarationName Name = GetNameForDeclarator(D);
|
||||||
|
|
||||||
|
// Check that there are no default arguments (C++ only).
|
||||||
|
if (getLangOptions().CPlusPlus)
|
||||||
|
CheckExtraCXXDefaultArguments(D);
|
||||||
|
|
||||||
|
if (R.getTypePtr()->isObjCInterfaceType()) {
|
||||||
|
Diag(D.getIdentifierLoc(), diag::err_statically_allocated_object)
|
||||||
|
<< D.getIdentifier();
|
||||||
|
InvalidDecl = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
VarDecl *NewVD;
|
||||||
|
VarDecl::StorageClass SC;
|
||||||
|
switch (D.getDeclSpec().getStorageClassSpec()) {
|
||||||
|
default: assert(0 && "Unknown storage class!");
|
||||||
|
case DeclSpec::SCS_unspecified: SC = VarDecl::None; break;
|
||||||
|
case DeclSpec::SCS_extern: SC = VarDecl::Extern; break;
|
||||||
|
case DeclSpec::SCS_static: SC = VarDecl::Static; break;
|
||||||
|
case DeclSpec::SCS_auto: SC = VarDecl::Auto; break;
|
||||||
|
case DeclSpec::SCS_register: SC = VarDecl::Register; break;
|
||||||
|
case DeclSpec::SCS_private_extern: SC = VarDecl::PrivateExtern; break;
|
||||||
|
case DeclSpec::SCS_mutable:
|
||||||
|
// mutable can only appear on non-static class members, so it's always
|
||||||
|
// an error here
|
||||||
|
Diag(D.getIdentifierLoc(), diag::err_mutable_nonmember);
|
||||||
|
InvalidDecl = true;
|
||||||
|
SC = VarDecl::None;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
IdentifierInfo *II = Name.getAsIdentifierInfo();
|
||||||
|
if (!II) {
|
||||||
|
Diag(D.getIdentifierLoc(), diag::err_bad_variable_name)
|
||||||
|
<< Name.getAsString();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DC->isRecord()) {
|
||||||
|
// This is a static data member for a C++ class.
|
||||||
|
NewVD = CXXClassVarDecl::Create(Context, cast<CXXRecordDecl>(DC),
|
||||||
|
D.getIdentifierLoc(), II,
|
||||||
|
R, LastDeclarator);
|
||||||
|
} else {
|
||||||
|
bool ThreadSpecified = D.getDeclSpec().isThreadSpecified();
|
||||||
|
if (S->getFnParent() == 0) {
|
||||||
|
// C99 6.9p2: The storage-class specifiers auto and register shall not
|
||||||
|
// appear in the declaration specifiers in an external declaration.
|
||||||
|
if (SC == VarDecl::Auto || SC == VarDecl::Register) {
|
||||||
|
Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope);
|
||||||
|
InvalidDecl = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
|
||||||
|
II, R, SC, LastDeclarator,
|
||||||
|
// FIXME: Move to DeclGroup...
|
||||||
|
D.getDeclSpec().getSourceRange().getBegin());
|
||||||
|
NewVD->setThreadSpecified(ThreadSpecified);
|
||||||
|
}
|
||||||
|
// Handle attributes prior to checking for duplicates in MergeVarDecl
|
||||||
|
ProcessDeclAttributes(NewVD, D);
|
||||||
|
|
||||||
|
// Handle GNU asm-label extension (encoded as an attribute).
|
||||||
|
if (Expr *E = (Expr*) D.getAsmLabel()) {
|
||||||
|
// The parser guarantees this is a string.
|
||||||
|
StringLiteral *SE = cast<StringLiteral>(E);
|
||||||
|
NewVD->addAttr(new AsmLabelAttr(std::string(SE->getStrData(),
|
||||||
|
SE->getByteLength())));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit an error if an address space was applied to decl with local storage.
|
||||||
|
// This includes arrays of objects with address space qualifiers, but not
|
||||||
|
// automatic variables that point to other address spaces.
|
||||||
|
// ISO/IEC TR 18037 S5.1.2
|
||||||
|
if (NewVD->hasLocalStorage() && (NewVD->getType().getAddressSpace() != 0)) {
|
||||||
|
Diag(D.getIdentifierLoc(), diag::err_as_qualified_auto_decl);
|
||||||
|
InvalidDecl = true;
|
||||||
|
}
|
||||||
|
// Merge the decl with the existing one if appropriate. If the decl is
|
||||||
|
// in an outer scope, it isn't the same thing.
|
||||||
|
if (PrevDecl && isDeclInScope(PrevDecl, DC, S)) {
|
||||||
|
if (isa<FieldDecl>(PrevDecl) && D.getCXXScopeSpec().isSet()) {
|
||||||
|
// The user tried to define a non-static data member
|
||||||
|
// out-of-line (C++ [dcl.meaning]p1).
|
||||||
|
Diag(NewVD->getLocation(), diag::err_nonstatic_member_out_of_line)
|
||||||
|
<< D.getCXXScopeSpec().getRange();
|
||||||
|
NewVD->Destroy(Context);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NewVD = MergeVarDecl(NewVD, PrevDecl);
|
||||||
|
if (NewVD == 0) return 0;
|
||||||
|
|
||||||
|
if (D.getCXXScopeSpec().isSet()) {
|
||||||
|
// No previous declaration in the qualifying scope.
|
||||||
|
Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member)
|
||||||
|
<< Name << D.getCXXScopeSpec().getRange();
|
||||||
|
InvalidDecl = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NewVD;
|
||||||
|
}
|
||||||
|
|
||||||
ScopedDecl*
|
ScopedDecl*
|
||||||
Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||||
QualType R, ScopedDecl *LastDeclarator,
|
QualType R, ScopedDecl *LastDeclarator,
|
||||||
|
|
Loading…
Reference in New Issue