Remove FileVarDecl and BlockVarDecl. They are replaced by VarDecl::isBlockVarDecl() and VarDecl::isFileVarDecl().

This is a fairly mechanical/large change. As a result, I avoided making any changes/simplifications that weren't directly related. I did break two Analysis tests. I also have a couple FIXME's in UninitializedValues.cpp. Ted, can you take a look? If the bug isn't obvious, I am happy to dig in and fix it (since I broke it).

llvm-svn: 49748
This commit is contained in:
Steve Naroff 2008-04-15 22:42:06 +00:00
parent 82b6673c44
commit 08899ff85d
21 changed files with 165 additions and 217 deletions

View File

@ -70,7 +70,7 @@ namespace {
FunctionDecl *SuperContructorFunctionDecl; FunctionDecl *SuperContructorFunctionDecl;
// ObjC string constant support. // ObjC string constant support.
FileVarDecl *ConstantStringClassReference; VarDecl *ConstantStringClassReference;
RecordDecl *NSStringRecord; RecordDecl *NSStringRecord;
// ObjC foreach break/continue generation support. // ObjC foreach break/continue generation support.
@ -367,7 +367,7 @@ void RewriteObjC::HandleTopLevelDecl(Decl *D) {
// Look for built-in declarations that we need to refer during the rewrite. // Look for built-in declarations that we need to refer during the rewrite.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
RewriteFunctionDecl(FD); RewriteFunctionDecl(FD);
} else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) { } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {
// declared in <Foundation/NSString.h> // declared in <Foundation/NSString.h>
if (strcmp(FVD->getName(), "_NSConstantStringClassReference") == 0) { if (strcmp(FVD->getName(), "_NSConstantStringClassReference") == 0) {
ConstantStringClassReference = FVD; ConstantStringClassReference = FVD;
@ -1776,7 +1776,7 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
// The minus 2 removes the begin/end double quotes. // The minus 2 removes the begin/end double quotes.
Preamble += utostr(prettyBuf.str().size()-2) + "};\n"; Preamble += utostr(prettyBuf.str().size()-2) + "};\n";
FileVarDecl *NewVD = FileVarDecl::Create(*Context, NULL, SourceLocation(), VarDecl *NewVD = VarDecl::Create(*Context, NULL, SourceLocation(),
&Context->Idents.get(S.c_str()), strType, &Context->Idents.get(S.c_str()), strType,
VarDecl::Static, NULL); VarDecl::Static, NULL);
DeclRefExpr *DRE = new DeclRefExpr(NewVD, strType, SourceLocation()); DeclRefExpr *DRE = new DeclRefExpr(NewVD, strType, SourceLocation());

View File

@ -146,6 +146,10 @@ protected:
StorageClass SC, ScopedDecl *PrevDecl) StorageClass SC, ScopedDecl *PrevDecl)
: ValueDecl(DK, CD, L, Id, T, PrevDecl), Init(0) { SClass = SC; } : ValueDecl(DK, CD, L, Id, T, PrevDecl), Init(0) { SClass = SC; }
public: public:
static VarDecl *Create(ASTContext &C, DeclContext *CD,
SourceLocation L, IdentifierInfo *Id,
QualType T, StorageClass S, ScopedDecl *PrevDecl);
StorageClass getStorageClass() const { return (StorageClass)SClass; } StorageClass getStorageClass() const { return (StorageClass)SClass; }
const Expr *getInit() const { return Init; } const Expr *getInit() const { return Init; }
@ -156,7 +160,7 @@ public:
/// is a non-static local variable. /// is a non-static local variable.
bool hasLocalStorage() const { bool hasLocalStorage() const {
if (getStorageClass() == None) if (getStorageClass() == None)
return getKind() != FileVar; return !isFileVarDecl();
// Return true for: Auto, Register. // Return true for: Auto, Register.
// Return false for: Extern, Static, PrivateExtern. // Return false for: Extern, Static, PrivateExtern.
@ -169,6 +173,29 @@ public:
/// as static variables declared within a function. /// as static variables declared within a function.
bool hasGlobalStorage() const { return !hasLocalStorage(); } bool hasGlobalStorage() const { return !hasLocalStorage(); }
/// isBlockVarDecl - Returns true for local variable declarations. Note that
/// this includes static variables inside of functions.
///
/// void foo() { int x; static int y; extern int z; }
///
bool isBlockVarDecl() const {
if (getKind() != Decl::Var)
return false;
if (DeclContext *DC = getDeclContext())
return DC->isFunctionOrMethod();
return false;
}
/// isFileVarDecl - Returns true for file scoped variable declaration.
bool isFileVarDecl() const {
if (getKind() != Decl::Var)
return false;
// FIXME: change when TranlationUnitDecl is added as a declaration context.
if (!getDeclContext())
return true;
return false;
}
// Implement isa/cast/dyncast/etc. // Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { static bool classof(const Decl *D) {
return D->getKind() >= VarFirst && D->getKind() <= VarLast; return D->getKind() >= VarFirst && D->getKind() <= VarLast;
@ -187,56 +214,9 @@ protected:
/// ReadImpl - Deserialize this VarDecl. Called by subclasses. /// ReadImpl - Deserialize this VarDecl. Called by subclasses.
virtual void ReadImpl(llvm::Deserializer& D, ASTContext& C); virtual void ReadImpl(llvm::Deserializer& D, ASTContext& C);
};
/// BlockVarDecl - Represent a local variable declaration. Note that this /// CreateImpl - Deserialize a VarDecl. Called by Decl::Create.
/// includes static variables inside of functions. static VarDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
///
/// void foo() { int x; static int y; extern int z; }
///
class BlockVarDecl : public VarDecl {
BlockVarDecl(DeclContext *CD, SourceLocation L,
IdentifierInfo *Id, QualType T, StorageClass S,
ScopedDecl *PrevDecl)
: VarDecl(BlockVar, CD, L, Id, T, S, PrevDecl) {}
public:
static BlockVarDecl *Create(ASTContext &C, DeclContext *CD, SourceLocation L,
IdentifierInfo *Id, QualType T, StorageClass S,
ScopedDecl *PrevDecl);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == BlockVar; }
static bool classof(const BlockVarDecl *D) { return true; }
protected:
/// CreateImpl - Deserialize a BlockVarDecl. Called by Decl::Create.
static BlockVarDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
};
/// FileVarDecl - Represent a file scoped variable declaration. This
/// will allow us to reason about external variable declarations and tentative
/// definitions (C99 6.9.2p2) using our type system (without storing a
/// pointer to the decl's scope, which is transient).
class FileVarDecl : public VarDecl {
FileVarDecl(DeclContext *CD, SourceLocation L,
IdentifierInfo *Id, QualType T, StorageClass S,
ScopedDecl *PrevDecl)
: VarDecl(FileVar, CD, L, Id, T, S, PrevDecl) {}
public:
static FileVarDecl *Create(ASTContext &C, DeclContext *CD,
SourceLocation L, IdentifierInfo *Id,
QualType T, StorageClass S, ScopedDecl *PrevDecl);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == FileVar; }
static bool classof(const FileVarDecl *D) { return true; }
protected:
/// CreateImpl - Deserialize a FileVarDecl. Called by Decl::Create.
static FileVarDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
}; };
/// ParmVarDecl - Represent a parameter to a function. /// ParmVarDecl - Represent a parameter to a function.

View File

@ -55,9 +55,7 @@ public:
// ValueDecl // ValueDecl
EnumConstant, EnumConstant,
Function, Function,
// VarDecl Var,
BlockVar,
FileVar,
ParmVar, ParmVar,
ObjCInterface, ObjCInterface,
ObjCCompatibleAlias, ObjCCompatibleAlias,
@ -76,7 +74,7 @@ public:
TagFirst = Enum , TagLast = Class, TagFirst = Enum , TagLast = Class,
RecordFirst = Struct , RecordLast = Class, RecordFirst = Struct , RecordLast = Class,
ValueFirst = EnumConstant , ValueLast = ParmVar, ValueFirst = EnumConstant , ValueLast = ParmVar,
VarFirst = BlockVar , VarLast = ParmVar VarFirst = Var , VarLast = ParmVar
}; };
/// IdentifierNamespace - According to C99 6.2.3, there are four namespaces, /// IdentifierNamespace - According to C99 6.2.3, there are four namespaces,
@ -151,8 +149,7 @@ public:
default: assert(0 && "Unknown decl kind!"); default: assert(0 && "Unknown decl kind!");
case Typedef: case Typedef:
case Function: case Function:
case BlockVar: case Var:
case FileVar:
case ParmVar: case ParmVar:
case EnumConstant: case EnumConstant:
case ObjCInterface: case ObjCInterface:

View File

@ -51,7 +51,7 @@ public:
struct ObserverTy { struct ObserverTy {
virtual ~ObserverTy(); virtual ~ObserverTy();
virtual void ObserveDeclRefExpr(ValTy& Val, AnalysisDataTy& AD, virtual void ObserveDeclRefExpr(ValTy& Val, AnalysisDataTy& AD,
DeclRefExpr* DR, BlockVarDecl* VD) = 0; DeclRefExpr* DR, VarDecl* VD) = 0;
}; };
}; };

View File

@ -54,8 +54,7 @@ public:
void VisitScopedDecl(ScopedDecl* D) { void VisitScopedDecl(ScopedDecl* D) {
switch (D->getKind()) { switch (D->getKind()) {
DISPATCH_CASE(Function,FunctionDecl) DISPATCH_CASE(Function,FunctionDecl)
DISPATCH_CASE(BlockVar,BlockVarDecl) // FIXME:Refine. VisitVarDecl? DISPATCH_CASE(Var,VarDecl)
DISPATCH_CASE(FileVar,FileVarDecl) // FIXME: (same)
DISPATCH_CASE(ParmVar,ParmVarDecl) // FIXME: (same) DISPATCH_CASE(ParmVar,ParmVarDecl) // FIXME: (same)
DISPATCH_CASE(EnumConstant,EnumConstantDecl) DISPATCH_CASE(EnumConstant,EnumConstantDecl)
DISPATCH_CASE(Typedef,TypedefDecl) DISPATCH_CASE(Typedef,TypedefDecl)
@ -70,8 +69,6 @@ public:
DEFAULT_DISPATCH(VarDecl) DEFAULT_DISPATCH(VarDecl)
DEFAULT_DISPATCH(FunctionDecl) DEFAULT_DISPATCH(FunctionDecl)
DEFAULT_DISPATCH_VARDECL(BlockVarDecl)
DEFAULT_DISPATCH_VARDECL(FileVarDecl)
DEFAULT_DISPATCH_VARDECL(ParmVarDecl) DEFAULT_DISPATCH_VARDECL(ParmVarDecl)
DEFAULT_DISPATCH(EnumConstantDecl) DEFAULT_DISPATCH(EnumConstantDecl)
DEFAULT_DISPATCH(TypedefDecl) DEFAULT_DISPATCH(TypedefDecl)

View File

@ -24,8 +24,7 @@ using namespace clang;
// temporary statistics gathering // temporary statistics gathering
static unsigned nFuncs = 0; static unsigned nFuncs = 0;
static unsigned nBlockVars = 0; static unsigned nVars = 0;
static unsigned nFileVars = 0;
static unsigned nParmVars = 0; static unsigned nParmVars = 0;
static unsigned nSUC = 0; static unsigned nSUC = 0;
static unsigned nEnumConst = 0; static unsigned nEnumConst = 0;
@ -59,8 +58,7 @@ const char *Decl::getDeclKindName() const {
default: assert(0 && "Unknown decl kind!"); default: assert(0 && "Unknown decl kind!");
case Typedef: return "Typedef"; case Typedef: return "Typedef";
case Function: return "Function"; case Function: return "Function";
case BlockVar: return "BlockVar"; case Var: return "Var";
case FileVar: return "FileVar";
case ParmVar: return "ParmVar"; case ParmVar: return "ParmVar";
case EnumConstant: return "EnumConstant"; case EnumConstant: return "EnumConstant";
case ObjCInterface: return "ObjCInterface"; case ObjCInterface: return "ObjCInterface";
@ -84,17 +82,14 @@ bool Decl::CollectingStats(bool Enable) {
void Decl::PrintStats() { void Decl::PrintStats() {
fprintf(stderr, "*** Decl Stats:\n"); fprintf(stderr, "*** Decl Stats:\n");
fprintf(stderr, " %d decls total.\n", fprintf(stderr, " %d decls total.\n",
int(nFuncs+nBlockVars+nFileVars+nParmVars+nFieldDecls+nSUC+ int(nFuncs+nVars+nParmVars+nFieldDecls+nSUC+
nEnumDecls+nEnumConst+nTypedef+nInterfaceDecls+nClassDecls+ nEnumDecls+nEnumConst+nTypedef+nInterfaceDecls+nClassDecls+
nMethodDecls+nProtocolDecls+nCategoryDecls+nIvarDecls)); nMethodDecls+nProtocolDecls+nCategoryDecls+nIvarDecls));
fprintf(stderr, " %d function decls, %d each (%d bytes)\n", fprintf(stderr, " %d function decls, %d each (%d bytes)\n",
nFuncs, (int)sizeof(FunctionDecl), int(nFuncs*sizeof(FunctionDecl))); nFuncs, (int)sizeof(FunctionDecl), int(nFuncs*sizeof(FunctionDecl)));
fprintf(stderr, " %d block variable decls, %d each (%d bytes)\n", fprintf(stderr, " %d variable decls, %d each (%d bytes)\n",
nBlockVars, (int)sizeof(BlockVarDecl), nVars, (int)sizeof(VarDecl),
int(nBlockVars*sizeof(BlockVarDecl))); int(nVars*sizeof(VarDecl)));
fprintf(stderr, " %d file variable decls, %d each (%d bytes)\n",
nFileVars, (int)sizeof(FileVarDecl),
int(nFileVars*sizeof(FileVarDecl)));
fprintf(stderr, " %d parameter variable decls, %d each (%d bytes)\n", fprintf(stderr, " %d parameter variable decls, %d each (%d bytes)\n",
nParmVars, (int)sizeof(ParmVarDecl), nParmVars, (int)sizeof(ParmVarDecl),
int(nParmVars*sizeof(ParmVarDecl))); int(nParmVars*sizeof(ParmVarDecl)));
@ -152,8 +147,8 @@ void Decl::PrintStats() {
int(nObjCPropertyDecl*sizeof(ObjCPropertyDecl))); int(nObjCPropertyDecl*sizeof(ObjCPropertyDecl)));
fprintf(stderr, "Total bytes = %d\n", fprintf(stderr, "Total bytes = %d\n",
int(nFuncs*sizeof(FunctionDecl)+nBlockVars*sizeof(BlockVarDecl)+ int(nFuncs*sizeof(FunctionDecl)+
nFileVars*sizeof(FileVarDecl)+nParmVars*sizeof(ParmVarDecl)+ nVars*sizeof(VarDecl)+nParmVars*sizeof(ParmVarDecl)+
nFieldDecls*sizeof(FieldDecl)+nSUC*sizeof(RecordDecl)+ nFieldDecls*sizeof(FieldDecl)+nSUC*sizeof(RecordDecl)+
nEnumDecls*sizeof(EnumDecl)+nEnumConst*sizeof(EnumConstantDecl)+ nEnumDecls*sizeof(EnumDecl)+nEnumConst*sizeof(EnumConstantDecl)+
nTypedef*sizeof(TypedefDecl)+ nTypedef*sizeof(TypedefDecl)+
@ -177,8 +172,7 @@ void Decl::addDeclKind(Kind k) {
switch (k) { switch (k) {
case Typedef: nTypedef++; break; case Typedef: nTypedef++; break;
case Function: nFuncs++; break; case Function: nFuncs++; break;
case BlockVar: nBlockVars++; break; case Var: nVars++; break;
case FileVar: nFileVars++; break;
case ParmVar: nParmVars++; break; case ParmVar: nParmVars++; break;
case EnumConstant: nEnumConst++; break; case EnumConstant: nEnumConst++; break;
case Field: nFieldDecls++; break; case Field: nFieldDecls++; break;
@ -204,23 +198,15 @@ void Decl::addDeclKind(Kind k) {
// Decl Allocation/Deallocation Method Implementations // Decl Allocation/Deallocation Method Implementations
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
BlockVarDecl *BlockVarDecl::Create(ASTContext &C, DeclContext *CD, VarDecl *VarDecl::Create(ASTContext &C, DeclContext *CD,
SourceLocation L, SourceLocation L,
IdentifierInfo *Id, QualType T, IdentifierInfo *Id, QualType T,
StorageClass S, ScopedDecl *PrevDecl) { StorageClass S, ScopedDecl *PrevDecl) {
void *Mem = C.getAllocator().Allocate<BlockVarDecl>(); void *Mem = C.getAllocator().Allocate<VarDecl>();
return new (Mem) BlockVarDecl(CD, L, Id, T, S, PrevDecl); return new (Mem) VarDecl(Var, CD, L, Id, T, S, PrevDecl);
} }
FileVarDecl *FileVarDecl::Create(ASTContext &C, DeclContext *CD,
SourceLocation L, IdentifierInfo *Id,
QualType T, StorageClass S,
ScopedDecl *PrevDecl) {
void *Mem = C.getAllocator().Allocate<FileVarDecl>();
return new (Mem) FileVarDecl(CD, L, Id, T, S, PrevDecl);
}
ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *CD, ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *CD,
SourceLocation L, IdentifierInfo *Id, SourceLocation L, IdentifierInfo *Id,
QualType T, StorageClass S, QualType T, StorageClass S,
@ -347,8 +333,7 @@ void Decl::Destroy(ASTContext& C) const {
CASE(Enum); CASE(Enum);
CASE(EnumConstant); CASE(EnumConstant);
CASE(Function); CASE(Function);
CASE(BlockVar); CASE(Var);
CASE(FileVar);
CASE(ParmVar); CASE(ParmVar);
CASE(ObjCInterface); CASE(ObjCInterface);
CASE(ObjCCompatibleAlias); CASE(ObjCCompatibleAlias);

View File

@ -41,8 +41,8 @@ Decl* Decl::Create(Deserializer& D, ASTContext& C) {
assert (false && "Not implemented."); assert (false && "Not implemented.");
break; break;
case BlockVar: case Var:
return BlockVarDecl::CreateImpl(D, C); return VarDecl::CreateImpl(D, C);
case Enum: case Enum:
return EnumDecl::CreateImpl(D, C); return EnumDecl::CreateImpl(D, C);
@ -53,9 +53,6 @@ Decl* Decl::Create(Deserializer& D, ASTContext& C) {
case Field: case Field:
return FieldDecl::CreateImpl(D, C); return FieldDecl::CreateImpl(D, C);
case FileVar:
return FileVarDecl::CreateImpl(D, C);
case ParmVar: case ParmVar:
return ParmVarDecl::CreateImpl(D, C); return ParmVarDecl::CreateImpl(D, C);
@ -195,13 +192,13 @@ void VarDecl::ReadImpl(Deserializer& D, ASTContext& C) {
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// BlockVarDecl Serialization. // VarDecl Serialization.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
BlockVarDecl* BlockVarDecl::CreateImpl(Deserializer& D, ASTContext& C) { VarDecl* VarDecl::CreateImpl(Deserializer& D, ASTContext& C) {
void *Mem = C.getAllocator().Allocate<BlockVarDecl>(); void *Mem = C.getAllocator().Allocate<VarDecl>();
BlockVarDecl* decl = VarDecl* decl =
new (Mem) BlockVarDecl(0, SourceLocation(), NULL, QualType(), None, NULL); new (Mem) VarDecl(Var, 0, SourceLocation(), NULL, QualType(), None, NULL);
decl->VarDecl::ReadImpl(D, C); decl->VarDecl::ReadImpl(D, C);
@ -209,21 +206,7 @@ BlockVarDecl* BlockVarDecl::CreateImpl(Deserializer& D, ASTContext& C) {
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// FileVarDecl Serialization. // ParmVarDecl Serialization.
//===----------------------------------------------------------------------===//
FileVarDecl* FileVarDecl::CreateImpl(Deserializer& D, ASTContext& C) {
void *Mem = C.getAllocator().Allocate<FileVarDecl>();
FileVarDecl* decl =
new (Mem) FileVarDecl(0, SourceLocation(), NULL, QualType(), None, NULL);
decl->VarDecl::ReadImpl(D, C);
return decl;
}
//===----------------------------------------------------------------------===//
// ParmDecl Serialization.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
void ParmVarDecl::EmitImpl(llvm::Serializer& S) const { void ParmVarDecl::EmitImpl(llvm::Serializer& S) const {

View File

@ -280,8 +280,7 @@ void StmtDumper::VisitDeclRefExpr(DeclRefExpr *Node) {
fprintf(F, " "); fprintf(F, " ");
switch (Node->getDecl()->getKind()) { switch (Node->getDecl()->getKind()) {
case Decl::Function: fprintf(F,"FunctionDecl"); break; case Decl::Function: fprintf(F,"FunctionDecl"); break;
case Decl::BlockVar: fprintf(F,"BlockVar"); break; case Decl::Var: fprintf(F,"Var"); break;
case Decl::FileVar: fprintf(F,"FileVar"); break;
case Decl::ParmVar: fprintf(F,"ParmVar"); break; case Decl::ParmVar: fprintf(F,"ParmVar"); break;
case Decl::EnumConstant: fprintf(F,"EnumConstant"); break; case Decl::EnumConstant: fprintf(F,"EnumConstant"); break;
case Decl::Typedef: fprintf(F,"Typedef"); break; case Decl::Typedef: fprintf(F,"Typedef"); break;

View File

@ -738,7 +738,7 @@ void GRExprEngine::VisitDeclStmt(DeclStmt* DS, GRExprEngine::NodeTy* Pred,
// In this context, Static => Local variable. // In this context, Static => Local variable.
assert (!VD->getStorageClass() == VarDecl::Static || assert (!VD->getStorageClass() == VarDecl::Static ||
!isa<FileVarDecl>(VD)); !VD->isFileVarDecl());
// If there is no initializer, set the value of the // If there is no initializer, set the value of the
// variable to "Undefined". // variable to "Undefined".

View File

@ -36,7 +36,7 @@ class VISIBILITY_HIDDEN RegisterDecls
public: public:
RegisterDecls(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {} RegisterDecls(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {}
void VisitBlockVarDecl(BlockVarDecl* VD) { AD.Register(VD); } void VisitBlockVarDecl(VarDecl* VD) { AD.Register(VD); }
CFG& getCFG() { return AD.getCFG(); } CFG& getCFG() { return AD.getCFG(); }
}; };
@ -80,14 +80,16 @@ public:
void VisitTerminator(Stmt* T) { } void VisitTerminator(Stmt* T) { }
BlockVarDecl* FindBlockVarDecl(Stmt* S); VarDecl* FindBlockVarDecl(Stmt* S);
}; };
static const bool Initialized = true; static const bool Initialized = true;
static const bool Uninitialized = false; static const bool Uninitialized = false;
bool TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) { bool TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
if (BlockVarDecl* VD = dyn_cast<BlockVarDecl>(DR->getDecl())) { // FIXME: Ted, can this be simplified?
VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl());
if (VD && VD->isBlockVarDecl()) {
if (AD.Observer) AD.Observer->ObserveDeclRefExpr(V,AD,DR,VD); if (AD.Observer) AD.Observer->ObserveDeclRefExpr(V,AD,DR,VD);
// Pseudo-hack to prevent cascade of warnings. If an accessed variable // Pseudo-hack to prevent cascade of warnings. If an accessed variable
@ -101,13 +103,15 @@ bool TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
else return Initialized; else return Initialized;
} }
BlockVarDecl* TransferFuncs::FindBlockVarDecl(Stmt *S) { VarDecl* TransferFuncs::FindBlockVarDecl(Stmt *S) {
for (;;) for (;;)
if (ParenExpr* P = dyn_cast<ParenExpr>(S)) { if (ParenExpr* P = dyn_cast<ParenExpr>(S)) {
S = P->getSubExpr(); continue; S = P->getSubExpr(); continue;
} }
else if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S)) { else if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S)) {
if (BlockVarDecl* VD = dyn_cast<BlockVarDecl>(DR->getDecl())) // FIXME: Ted, can this be simplified?
VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl());
if (VD->isBlockVarDecl())
return VD; return VD;
else else
return NULL; return NULL;
@ -116,7 +120,9 @@ BlockVarDecl* TransferFuncs::FindBlockVarDecl(Stmt *S) {
} }
bool TransferFuncs::VisitBinaryOperator(BinaryOperator* B) { bool TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {
if (BlockVarDecl* VD = FindBlockVarDecl(B->getLHS())) // FIXME: Ted, can this be simplified?
VarDecl* VD = FindBlockVarDecl(B->getLHS());
if (VD && VD->isBlockVarDecl())
if (B->isAssignmentOp()) { if (B->isAssignmentOp()) {
if (B->getOpcode() == BinaryOperator::Assign) if (B->getOpcode() == BinaryOperator::Assign)
return V(VD,AD) = Visit(B->getRHS()); return V(VD,AD) = Visit(B->getRHS());
@ -128,8 +134,9 @@ bool TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {
} }
bool TransferFuncs::VisitDeclStmt(DeclStmt* S) { bool TransferFuncs::VisitDeclStmt(DeclStmt* S) {
for (ScopedDecl* D = S->getDecl(); D != NULL; D = D->getNextDeclarator()) for (ScopedDecl* D = S->getDecl(); D != NULL; D = D->getNextDeclarator()) {
if (BlockVarDecl* VD = dyn_cast<BlockVarDecl>(D)) { VarDecl *VD = dyn_cast<VarDecl>(D);
if (VD && VD->isBlockVarDecl()) {
if (Stmt* I = VD->getInit()) if (Stmt* I = VD->getInit())
V(VD,AD) = AD.FullUninitTaint ? V(cast<Expr>(I),AD) : Initialized; V(VD,AD) = AD.FullUninitTaint ? V(cast<Expr>(I),AD) : Initialized;
else { else {
@ -149,7 +156,7 @@ bool TransferFuncs::VisitDeclStmt(DeclStmt* S) {
V(VD,AD) = Uninitialized; V(VD,AD) = Uninitialized;
} }
} }
}
return Uninitialized; // Value is never consumed. return Uninitialized; // Value is never consumed.
} }
@ -161,9 +168,9 @@ bool TransferFuncs::VisitCallExpr(CallExpr* C) {
bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) { bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
switch (U->getOpcode()) { switch (U->getOpcode()) {
case UnaryOperator::AddrOf: case UnaryOperator::AddrOf:
if (BlockVarDecl* VD = FindBlockVarDecl(U->getSubExpr())) VarDecl* VD = FindBlockVarDecl(U->getSubExpr());
if (VD && VD->isBlockVarDecl())
return V(VD,AD) = Initialized; return V(VD,AD) = Initialized;
break; break;
case UnaryOperator::SizeOf: case UnaryOperator::SizeOf:
@ -240,7 +247,7 @@ class VISIBILITY_HIDDEN UninitializedValuesChecker
ASTContext &Ctx; ASTContext &Ctx;
Diagnostic &Diags; Diagnostic &Diags;
llvm::SmallPtrSet<BlockVarDecl*,10> AlreadyWarned; llvm::SmallPtrSet<VarDecl*,10> AlreadyWarned;
public: public:
UninitializedValuesChecker(ASTContext &ctx, Diagnostic &diags) UninitializedValuesChecker(ASTContext &ctx, Diagnostic &diags)
@ -248,7 +255,7 @@ public:
virtual void ObserveDeclRefExpr(UninitializedValues::ValTy& V, virtual void ObserveDeclRefExpr(UninitializedValues::ValTy& V,
UninitializedValues::AnalysisDataTy& AD, UninitializedValues::AnalysisDataTy& AD,
DeclRefExpr* DR, BlockVarDecl* VD) { DeclRefExpr* DR, VarDecl* VD) {
assert ( AD.isTracked(VD) && "Unknown VarDecl."); assert ( AD.isTracked(VD) && "Unknown VarDecl.");

View File

@ -23,8 +23,6 @@ using namespace CodeGen;
void CodeGenFunction::EmitDecl(const Decl &D) { void CodeGenFunction::EmitDecl(const Decl &D) {
switch (D.getKind()) { switch (D.getKind()) {
default: assert(0 && "Unknown decl kind!"); default: assert(0 && "Unknown decl kind!");
case Decl::FileVar:
assert(0 && "Should not see file-scope variables inside a function!");
case Decl::ParmVar: case Decl::ParmVar:
assert(0 && "Parmdecls should not be in declstmts!"); assert(0 && "Parmdecls should not be in declstmts!");
case Decl::Typedef: // typedef int X; case Decl::Typedef: // typedef int X;
@ -36,8 +34,11 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
// None of these decls require codegen support. // None of these decls require codegen support.
return; return;
case Decl::BlockVar: case Decl::Var:
return EmitBlockVarDecl(cast<BlockVarDecl>(D)); if (cast<VarDecl>(D).isBlockVarDecl())
return EmitBlockVarDecl(cast<VarDecl>(D));
assert(0 && "Should not see file-scope variables inside a function!");
case Decl::EnumConstant: case Decl::EnumConstant:
return EmitEnumConstantDecl(cast<EnumConstantDecl>(D)); return EmitEnumConstantDecl(cast<EnumConstantDecl>(D));
} }
@ -49,7 +50,7 @@ void CodeGenFunction::EmitEnumConstantDecl(const EnumConstantDecl &D) {
/// EmitBlockVarDecl - This method handles emission of any variable declaration /// EmitBlockVarDecl - This method handles emission of any variable declaration
/// inside a function, including static vars etc. /// inside a function, including static vars etc.
void CodeGenFunction::EmitBlockVarDecl(const BlockVarDecl &D) { void CodeGenFunction::EmitBlockVarDecl(const VarDecl &D) {
switch (D.getStorageClass()) { switch (D.getStorageClass()) {
case VarDecl::Static: case VarDecl::Static:
return EmitStaticBlockVarDecl(D); return EmitStaticBlockVarDecl(D);
@ -65,7 +66,7 @@ void CodeGenFunction::EmitBlockVarDecl(const BlockVarDecl &D) {
} }
} }
void CodeGenFunction::EmitStaticBlockVarDecl(const BlockVarDecl &D) { void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) {
QualType Ty = D.getType(); QualType Ty = D.getType();
assert(Ty->isConstantSizeType() && "VLAs can't be static"); assert(Ty->isConstantSizeType() && "VLAs can't be static");
@ -99,7 +100,7 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const BlockVarDecl &D) {
/// EmitLocalBlockVarDecl - Emit code and set up an entry in LocalDeclMap for a /// EmitLocalBlockVarDecl - Emit code and set up an entry in LocalDeclMap for a
/// variable declaration with auto, register, or no storage class specifier. /// variable declaration with auto, register, or no storage class specifier.
/// These turn into simple stack objects. /// These turn into simple stack objects.
void CodeGenFunction::EmitLocalBlockVarDecl(const BlockVarDecl &D) { void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
QualType Ty = D.getType(); QualType Ty = D.getType();
llvm::Value *DeclPtr; llvm::Value *DeclPtr;

View File

@ -338,20 +338,20 @@ void CodeGenFunction::EmitStoreThroughOCUComponentLValue(RValue Src, LValue Dst,
LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
const ValueDecl *D = E->getDecl(); const VarDecl *VD = dyn_cast<VarDecl>(E->getDecl());
if (isa<BlockVarDecl>(D) || isa<ParmVarDecl>(D)) {
const VarDecl *VD = cast<VarDecl>(D); if (VD && (VD->isBlockVarDecl() || isa<ParmVarDecl>(VD))) {
if (VD->getStorageClass() == VarDecl::Extern) if (VD->getStorageClass() == VarDecl::Extern)
return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(VD, false)); return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(VD, false));
else { else {
llvm::Value *V = LocalDeclMap[D]; llvm::Value *V = LocalDeclMap[VD];
assert(V && "BlockVarDecl not entered in LocalDeclMap?"); assert(V && "BlockVarDecl not entered in LocalDeclMap?");
return LValue::MakeAddr(V); return LValue::MakeAddr(V);
} }
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { } else if (VD && VD->isFileVarDecl()) {
return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(VD, false));
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl())) {
return LValue::MakeAddr(CGM.GetAddrOfFunctionDecl(FD, false)); return LValue::MakeAddr(CGM.GetAddrOfFunctionDecl(FD, false));
} else if (const FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(FVD, false));
} }
assert(0 && "Unimp declref"); assert(0 && "Unimp declref");
//an invalid LValue, but the assert will //an invalid LValue, but the assert will

View File

@ -541,11 +541,13 @@ public:
ValueDecl *Decl = cast<DeclRefExpr>(E)->getDecl(); ValueDecl *Decl = cast<DeclRefExpr>(E)->getDecl();
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl)) if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
return CGM.GetAddrOfFunctionDecl(FD, false); return CGM.GetAddrOfFunctionDecl(FD, false);
if (const FileVarDecl* VD = dyn_cast<FileVarDecl>(Decl)) if (const VarDecl* VD = dyn_cast<VarDecl>(Decl)) {
if (VD->isFileVarDecl())
return CGM.GetAddrOfGlobalVar(VD, false); return CGM.GetAddrOfGlobalVar(VD, false);
if (const BlockVarDecl* BVD = dyn_cast<BlockVarDecl>(Decl)) { else if (VD->isBlockVarDecl()) {
assert(CGF && "Can't access static local vars without CGF"); assert(CGF && "Can't access static local vars without CGF");
return CGF->GetAddrOfStaticLocalVar(BVD); return CGF->GetAddrOfStaticLocalVar(VD);
}
} }
break; break;
} }

View File

@ -42,7 +42,7 @@ llvm::BasicBlock *CodeGenFunction::getBasicBlockForLabel(const LabelStmt *S) {
} }
llvm::Constant * llvm::Constant *
CodeGenFunction::GetAddrOfStaticLocalVar(const BlockVarDecl *BVD) { CodeGenFunction::GetAddrOfStaticLocalVar(const VarDecl *BVD) {
return cast<llvm::Constant>(LocalDeclMap[BVD]); return cast<llvm::Constant>(LocalDeclMap[BVD]);
} }

View File

@ -70,7 +70,7 @@ namespace clang {
class ObjCIvarRefExpr; class ObjCIvarRefExpr;
class MemberExpr; class MemberExpr;
class BlockVarDecl; class VarDecl;
class EnumConstantDecl; class EnumConstantDecl;
class ParmVarDecl; class ParmVarDecl;
class FieldDecl; class FieldDecl;
@ -344,16 +344,16 @@ public:
const CGRecordLayout *getCGRecordLayout(CodeGenTypes &CGT, QualType RTy); const CGRecordLayout *getCGRecordLayout(CodeGenTypes &CGT, QualType RTy);
/// GetAddrOfStaticLocalVar - Return the address of a static local variable. /// GetAddrOfStaticLocalVar - Return the address of a static local variable.
llvm::Constant *GetAddrOfStaticLocalVar(const BlockVarDecl *BVD); llvm::Constant *GetAddrOfStaticLocalVar(const VarDecl *BVD);
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
// Declaration Emission // Declaration Emission
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
void EmitDecl(const Decl &D); void EmitDecl(const Decl &D);
void EmitEnumConstantDecl(const EnumConstantDecl &D); void EmitEnumConstantDecl(const EnumConstantDecl &D);
void EmitBlockVarDecl(const BlockVarDecl &D); void EmitBlockVarDecl(const VarDecl &D);
void EmitLocalBlockVarDecl(const BlockVarDecl &D); void EmitLocalBlockVarDecl(const VarDecl &D);
void EmitStaticBlockVarDecl(const BlockVarDecl &D); void EmitStaticBlockVarDecl(const VarDecl &D);
void EmitParmDecl(const ParmVarDecl &D, llvm::Value *Arg); void EmitParmDecl(const ParmVarDecl &D, llvm::Value *Arg);
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//

View File

@ -288,7 +288,7 @@ llvm::Constant *CodeGenModule::EmitGlobalInit(const Expr *Expr) {
return EmitConstantExpr(Expr); return EmitConstantExpr(Expr);
} }
void CodeGenModule::EmitGlobalVar(const FileVarDecl *D) { void CodeGenModule::EmitGlobalVar(const VarDecl *D) {
// If this is just a forward declaration of the variable, don't emit it now, // If this is just a forward declaration of the variable, don't emit it now,
// allow it to be emitted lazily on its first use. // allow it to be emitted lazily on its first use.
if (D->getStorageClass() == VarDecl::Extern && D->getInit() == 0) if (D->getStorageClass() == VarDecl::Extern && D->getInit() == 0)
@ -352,8 +352,9 @@ void CodeGenModule::EmitGlobalVar(const FileVarDecl *D) {
/// EmitGlobalVarDeclarator - Emit all the global vars attached to the specified /// EmitGlobalVarDeclarator - Emit all the global vars attached to the specified
/// declarator chain. /// declarator chain.
void CodeGenModule::EmitGlobalVarDeclarator(const FileVarDecl *D) { void CodeGenModule::EmitGlobalVarDeclarator(const VarDecl *D) {
for (; D; D = cast_or_null<FileVarDecl>(D->getNextDeclarator())) for (; D; D = cast_or_null<VarDecl>(D->getNextDeclarator()))
if (D->isFileVarDecl())
EmitGlobalVar(D); EmitGlobalVar(D);
} }

View File

@ -37,7 +37,6 @@ namespace clang {
class ValueDecl; class ValueDecl;
class VarDecl; class VarDecl;
class TypeDecl; class TypeDecl;
class FileVarDecl;
struct LangOptions; struct LangOptions;
class Diagnostic; class Diagnostic;
@ -103,8 +102,8 @@ public:
void EmitObjCMethod(const ObjCMethodDecl *OMD); void EmitObjCMethod(const ObjCMethodDecl *OMD);
void EmitFunction(const FunctionDecl *FD); void EmitFunction(const FunctionDecl *FD);
void EmitGlobalVar(const FileVarDecl *D); void EmitGlobalVar(const VarDecl *D);
void EmitGlobalVarDeclarator(const FileVarDecl *D); void EmitGlobalVarDeclarator(const VarDecl *D);
void UpdateCompletedType(const TagDecl *D); void UpdateCompletedType(const TagDecl *D);
llvm::Constant *EmitGlobalInit(const Expr *E); llvm::Constant *EmitGlobalInit(const Expr *E);
llvm::Constant *EmitConstantExpr(const Expr *E, CodeGenFunction *CGF = 0); llvm::Constant *EmitConstantExpr(const Expr *E, CodeGenFunction *CGF = 0);

View File

@ -63,8 +63,9 @@ namespace {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Builder->EmitFunction(FD); Builder->EmitFunction(FD);
} else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) { } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
Builder->EmitGlobalVarDeclarator(FVD); if (VD->isFileVarDecl())
Builder->EmitGlobalVarDeclarator(VD);
} else if (isa<ObjCClassDecl>(D) || isa<ObjCCategoryDecl>(D)) { } else if (isa<ObjCClassDecl>(D) || isa<ObjCCategoryDecl>(D)) {
// Forward declaration. Only used for type checking. // Forward declaration. Only used for type checking.
} else if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)){ } else if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)){

View File

@ -372,26 +372,23 @@ VarDecl *Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
return New; return New;
} }
// We've verified the types match, now handle "tentative" definitions. // We've verified the types match, now handle "tentative" definitions.
FileVarDecl *OldFSDecl = dyn_cast<FileVarDecl>(Old); if (Old->isFileVarDecl() && New->isFileVarDecl()) {
FileVarDecl *NewFSDecl = dyn_cast<FileVarDecl>(New);
if (OldFSDecl && NewFSDecl) {
// Handle C "tentative" external object definitions (C99 6.9.2). // Handle C "tentative" external object definitions (C99 6.9.2).
bool OldIsTentative = false; bool OldIsTentative = false;
bool NewIsTentative = false; bool NewIsTentative = false;
if (!OldFSDecl->getInit() && if (!Old->getInit() &&
(OldFSDecl->getStorageClass() == VarDecl::None || (Old->getStorageClass() == VarDecl::None ||
OldFSDecl->getStorageClass() == VarDecl::Static)) Old->getStorageClass() == VarDecl::Static))
OldIsTentative = true; OldIsTentative = true;
// FIXME: this check doesn't work (since the initializer hasn't been // FIXME: this check doesn't work (since the initializer hasn't been
// attached yet). This check should be moved to FinalizeDeclaratorGroup. // attached yet). This check should be moved to FinalizeDeclaratorGroup.
// Unfortunately, by the time we get to FinializeDeclaratorGroup, we've // Unfortunately, by the time we get to FinializeDeclaratorGroup, we've
// thrown out the old decl. // thrown out the old decl.
if (!NewFSDecl->getInit() && if (!New->getInit() &&
(NewFSDecl->getStorageClass() == VarDecl::None || (New->getStorageClass() == VarDecl::None ||
NewFSDecl->getStorageClass() == VarDecl::Static)) New->getStorageClass() == VarDecl::Static))
; // change to NewIsTentative = true; once the code is moved. ; // change to NewIsTentative = true; once the code is moved.
if (NewIsTentative || OldIsTentative) if (NewIsTentative || OldIsTentative)
@ -880,13 +877,11 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
R.getAsString()); R.getAsString());
InvalidDecl = true; InvalidDecl = true;
} }
NewVD = FileVarDecl::Create(Context, CurContext, D.getIdentifierLoc(), NewVD = VarDecl::Create(Context, CurContext, D.getIdentifierLoc(),
II, R, SC, II, R, SC, LastDeclarator);
LastDeclarator);
} else { } else {
NewVD = BlockVarDecl::Create(Context, CurContext, D.getIdentifierLoc(), NewVD = VarDecl::Create(Context, CurContext, D.getIdentifierLoc(),
II, R, SC, II, R, SC, LastDeclarator);
LastDeclarator);
} }
// Handle attributes prior to checking for duplicates in MergeVarDecl // Handle attributes prior to checking for duplicates in MergeVarDecl
HandleDeclAttributes(NewVD, D.getDeclSpec().getAttributes(), HandleDeclAttributes(NewVD, D.getDeclSpec().getAttributes(),
@ -952,23 +947,23 @@ void Sema::AddInitializerToDecl(DeclTy *dcl, ExprTy *init) {
// Get the decls type and save a reference for later, since // Get the decls type and save a reference for later, since
// CheckInitializerTypes may change it. // CheckInitializerTypes may change it.
QualType DclT = VDecl->getType(), SavT = DclT; QualType DclT = VDecl->getType(), SavT = DclT;
if (BlockVarDecl *BVD = dyn_cast<BlockVarDecl>(VDecl)) { if (VDecl->isBlockVarDecl()) {
VarDecl::StorageClass SC = BVD->getStorageClass(); VarDecl::StorageClass SC = VDecl->getStorageClass();
if (SC == VarDecl::Extern) { // C99 6.7.8p5 if (SC == VarDecl::Extern) { // C99 6.7.8p5
Diag(VDecl->getLocation(), diag::err_block_extern_cant_init); Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
BVD->setInvalidDecl(); VDecl->setInvalidDecl();
} else if (!BVD->isInvalidDecl()) { } else if (!VDecl->isInvalidDecl()) {
if (CheckInitializerTypes(Init, DclT)) if (CheckInitializerTypes(Init, DclT))
BVD->setInvalidDecl(); VDecl->setInvalidDecl();
if (SC == VarDecl::Static) // C99 6.7.8p4. if (SC == VarDecl::Static) // C99 6.7.8p4.
CheckForConstantInitializer(Init, DclT); CheckForConstantInitializer(Init, DclT);
} }
} else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(VDecl)) { } else if (VDecl->isFileVarDecl()) {
if (FVD->getStorageClass() == VarDecl::Extern) if (VDecl->getStorageClass() == VarDecl::Extern)
Diag(VDecl->getLocation(), diag::warn_extern_init); Diag(VDecl->getLocation(), diag::warn_extern_init);
if (!FVD->isInvalidDecl()) if (!VDecl->isInvalidDecl())
if (CheckInitializerTypes(Init, DclT)) if (CheckInitializerTypes(Init, DclT))
FVD->setInvalidDecl(); VDecl->setInvalidDecl();
// C99 6.7.8p4. All file scoped initializers need to be constant. // C99 6.7.8p4. All file scoped initializers need to be constant.
CheckForConstantInitializer(Init, DclT); CheckForConstantInitializer(Init, DclT);
@ -1012,13 +1007,12 @@ Sema::DeclTy *Sema::FinalizeDeclaratorGroup(Scope *S, DeclTy *group) {
VarDecl *IDecl = dyn_cast<VarDecl>(ID); VarDecl *IDecl = dyn_cast<VarDecl>(ID);
if (!IDecl) if (!IDecl)
continue; continue;
FileVarDecl *FVD = dyn_cast<FileVarDecl>(IDecl);
BlockVarDecl *BVD = dyn_cast<BlockVarDecl>(IDecl);
QualType T = IDecl->getType(); QualType T = IDecl->getType();
// C99 6.7.5.2p2: If an identifier is declared to be an object with // C99 6.7.5.2p2: If an identifier is declared to be an object with
// static storage duration, it shall not have a variable length array. // static storage duration, it shall not have a variable length array.
if ((FVD || BVD) && IDecl->getStorageClass() == VarDecl::Static) { if ((IDecl->isFileVarDecl() || IDecl->isBlockVarDecl()) &&
IDecl->getStorageClass() == VarDecl::Static) {
if (T->getAsVariableArrayType()) { if (T->getAsVariableArrayType()) {
Diag(IDecl->getLocation(), diag::err_typecheck_illegal_vla); Diag(IDecl->getLocation(), diag::err_typecheck_illegal_vla);
IDecl->setInvalidDecl(); IDecl->setInvalidDecl();
@ -1026,7 +1020,8 @@ Sema::DeclTy *Sema::FinalizeDeclaratorGroup(Scope *S, DeclTy *group) {
} }
// Block scope. C99 6.7p7: If an identifier for an object is declared with // Block scope. C99 6.7p7: If an identifier for an object is declared with
// no linkage (C99 6.2.2p6), the type for the object shall be complete... // no linkage (C99 6.2.2p6), the type for the object shall be complete...
if (BVD && IDecl->getStorageClass() != VarDecl::Extern) { if (IDecl->isBlockVarDecl() &&
IDecl->getStorageClass() != VarDecl::Extern) {
if (T->isIncompleteType() && !IDecl->isInvalidDecl()) { if (T->isIncompleteType() && !IDecl->isInvalidDecl()) {
Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type, Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type,
T.getAsString()); T.getAsString());
@ -1038,8 +1033,9 @@ Sema::DeclTy *Sema::FinalizeDeclaratorGroup(Scope *S, DeclTy *group) {
// storage-class specifier or with the storage-class specifier "static", // storage-class specifier or with the storage-class specifier "static",
// constitutes a tentative definition. Note: A tentative definition with // constitutes a tentative definition. Note: A tentative definition with
// external linkage is valid (C99 6.2.2p5). // external linkage is valid (C99 6.2.2p5).
if (FVD && !FVD->getInit() && (FVD->getStorageClass() == VarDecl::Static || if (IDecl && !IDecl->getInit() &&
FVD->getStorageClass() == VarDecl::None)) { (IDecl->getStorageClass() == VarDecl::Static ||
IDecl->getStorageClass() == VarDecl::None)) {
if (T->isIncompleteArrayType()) { if (T->isIncompleteArrayType()) {
// C99 6.9.2 (p2, p5): Implicit initialization causes an incomplete // C99 6.9.2 (p2, p5): Implicit initialization causes an incomplete
// array to be completed. Don't issue a diagnostic. // array to be completed. Don't issue a diagnostic.

View File

@ -74,13 +74,14 @@ namespace {
return S->Diag(DRE->getSourceRange().getBegin(), return S->Diag(DRE->getSourceRange().getBegin(),
diag::err_param_default_argument_references_param, diag::err_param_default_argument_references_param,
Param->getName(), DefaultArg->getSourceRange()); Param->getName(), DefaultArg->getSourceRange());
} else if (BlockVarDecl *BlockVar = dyn_cast<BlockVarDecl>(Decl)) { } else if (VarDecl *VDecl = dyn_cast<VarDecl>(Decl)) {
// C++ [dcl.fct.default]p7 // C++ [dcl.fct.default]p7
// Local variables shall not be used in default argument // Local variables shall not be used in default argument
// expressions. // expressions.
if (VDecl->isBlockVarDecl())
return S->Diag(DRE->getSourceRange().getBegin(), return S->Diag(DRE->getSourceRange().getBegin(),
diag::err_param_default_argument_references_local, diag::err_param_default_argument_references_local,
BlockVar->getName(), DefaultArg->getSourceRange()); VDecl->getName(), DefaultArg->getSourceRange());
} }
// FIXME: when Clang has support for member functions, "this" // FIXME: when Clang has support for member functions, "this"

View File

@ -521,10 +521,10 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
// C99 6.8.5p3: The declaration part of a 'for' statement shall only declare // C99 6.8.5p3: The declaration part of a 'for' statement shall only declare
// identifiers for objects having storage class 'auto' or 'register'. // identifiers for objects having storage class 'auto' or 'register'.
for (ScopedDecl *D = DS->getDecl(); D; D = D->getNextDeclarator()) { for (ScopedDecl *D = DS->getDecl(); D; D = D->getNextDeclarator()) {
BlockVarDecl *BVD = dyn_cast<BlockVarDecl>(D); VarDecl *VD = dyn_cast<VarDecl>(D);
if (BVD && !BVD->hasLocalStorage()) if (VD && VD->isBlockVarDecl() && !VD->hasLocalStorage())
BVD = 0; VD = 0;
if (BVD == 0) if (VD == 0)
Diag(dyn_cast<ScopedDecl>(D)->getLocation(), Diag(dyn_cast<ScopedDecl>(D)->getLocation(),
diag::err_non_variable_decl_in_for); diag::err_non_variable_decl_in_for);
// FIXME: mark decl erroneous! // FIXME: mark decl erroneous!
@ -556,13 +556,12 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
// C99 6.8.5p3: The declaration part of a 'for' statement shall only declare // C99 6.8.5p3: The declaration part of a 'for' statement shall only declare
// identifiers for objects having storage class 'auto' or 'register'. // identifiers for objects having storage class 'auto' or 'register'.
ScopedDecl *D = DS->getDecl(); ScopedDecl *D = DS->getDecl();
BlockVarDecl *BVD = cast<BlockVarDecl>(D); VarDecl *VD = cast<VarDecl>(D);
if (!BVD->hasLocalStorage()) if (VD->isBlockVarDecl() && !VD->hasLocalStorage())
return Diag(BVD->getLocation(), diag::err_non_variable_decl_in_for); return Diag(VD->getLocation(), diag::err_non_variable_decl_in_for);
if (D->getNextDeclarator()) if (D->getNextDeclarator())
return Diag(D->getLocation(), diag::err_toomany_element_decls); return Diag(D->getLocation(), diag::err_toomany_element_decls);
} } else
else
FirstType = static_cast<Expr*>(first)->getType(); FirstType = static_cast<Expr*>(first)->getType();
if (!isObjCObjectPointerType(FirstType)) if (!isObjCObjectPointerType(FirstType))
Diag(ForLoc, diag::err_selector_element_type, Diag(ForLoc, diag::err_selector_element_type,