[class.local] p1 and p3. Also, add back the xcodeproj file.

llvm-svn: 74027
This commit is contained in:
Anders Carlsson
2009-06-24 00:10:43 +00:00
parent 5a495fea07
commit 946b86d91a
8 changed files with 1943 additions and 15 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -449,6 +449,15 @@ public:
/// getDestructor - Returns the destructor decl for this class.
const CXXDestructorDecl *getDestructor(ASTContext &Context);
/// isLocalClass - If the class is a local class [class.local], returns
/// the enclosing function declaration.
const FunctionDecl *isLocalClass() const {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(getDeclContext()))
return RD->isLocalClass();
return dyn_cast<FunctionDecl>(getDeclContext());
}
/// viewInheritance - Renders and displays an inheritance diagram
/// for this C++ class and all of its base classes (transitively) using
/// GraphViz.

View File

@@ -1603,6 +1603,12 @@ def err_anonymous_record_nonpublic_member : Error<
"anonymous %select{struct|union}0 cannot contain a "
"%select{private|protected}1 data member">;
// C++ local classes
def err_reference_to_local_var_in_enclosing_function : Error<
"reference to local variable %0 declared in enclosed function %1">;
def note_local_variable_declared_here : Note<
"%0 declared here">;
// C++ derived classes
def err_base_clause_on_union : Error<"unions cannot have base classes">;
def err_base_must_be_class : Error<"base specifier must name a class">;

View File

@@ -1377,9 +1377,10 @@ public:
bool HasTrailingLParen,
const CXXScopeSpec &SS,
bool isAddressOfOperand);
DeclRefExpr *BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
bool TypeDependent, bool ValueDependent,
const CXXScopeSpec *SS = 0);
OwningExprResult BuildDeclRefExpr(NamedDecl *D, QualType Ty,
SourceLocation Loc, bool TypeDependent,
bool ValueDependent,
const CXXScopeSpec *SS = 0);
VarDecl *BuildAnonymousStructUnionMemberPath(FieldDecl *Field,
llvm::SmallVectorImpl<FieldDecl *> &Path);
OwningExprResult

View File

@@ -623,17 +623,36 @@ Sema::OwningExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
/// BuildDeclRefExpr - Build either a DeclRefExpr or a
/// QualifiedDeclRefExpr based on whether or not SS is a
/// nested-name-specifier.
DeclRefExpr *
Sema::OwningExprResult
Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
bool TypeDependent, bool ValueDependent,
const CXXScopeSpec *SS) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
if (const FunctionDecl *FD = MD->getParent()->isLocalClass()) {
if (VD->hasLocalStorage() && VD->getDeclContext() != CurContext) {
Diag(Loc, diag::err_reference_to_local_var_in_enclosing_function)
<< D->getIdentifier() << FD->getDeclName();
Diag(D->getLocation(), diag::note_local_variable_declared_here)
<< D->getIdentifier();
return ExprError();
}
}
}
}
MarkDeclarationReferenced(Loc, D);
Expr *E;
if (SS && !SS->isEmpty()) {
return new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent,
ValueDependent, SS->getRange(),
E = new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent,
ValueDependent, SS->getRange(),
static_cast<NestedNameSpecifier *>(SS->getScopeRep()));
} else
return new (Context) DeclRefExpr(D, Ty, Loc, TypeDependent, ValueDependent);
E = new (Context) DeclRefExpr(D, Ty, Loc, TypeDependent, ValueDependent);
return Owned(E);
}
/// getObjectForAnonymousRecordDecl - Retrieve the (unnamed) field or
@@ -968,7 +987,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
// The pointer is type- and value-dependent if it points into something
// dependent.
bool Dependent = DC->isDependentContext();
return Owned(BuildDeclRefExpr(D, DType, Loc, Dependent, Dependent, SS));
return BuildDeclRefExpr(D, DType, Loc, Dependent, Dependent, SS);
}
}
}
@@ -1061,11 +1080,11 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
// Make the DeclRefExpr or BlockDeclRefExpr for the decl.
if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D))
return Owned(BuildDeclRefExpr(Ovl, Context.OverloadTy, Loc,
false, false, SS));
return BuildDeclRefExpr(Ovl, Context.OverloadTy, Loc,
false, false, SS);
else if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
return Owned(BuildDeclRefExpr(Template, Context.OverloadTy, Loc,
false, false, SS));
return BuildDeclRefExpr(Template, Context.OverloadTy, Loc,
false, false, SS);
ValueDecl *VD = cast<ValueDecl>(D);
// Check whether this declaration can be used. Note that we suppress
@@ -1113,7 +1132,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
QualType NoProtoType = T;
if (const FunctionProtoType *Proto = T->getAsFunctionProtoType())
NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType());
return Owned(BuildDeclRefExpr(VD, NoProtoType, Loc, false, false, SS));
return BuildDeclRefExpr(VD, NoProtoType, Loc, false, false, SS);
}
}
@@ -1194,8 +1213,8 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
}
}
return Owned(BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc,
TypeDependent, ValueDependent, SS));
return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc,
TypeDependent, ValueDependent, SS);
}
Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,

View File

@@ -835,6 +835,7 @@ static bool IsReturnCopyElidable(ASTContext &Ctx, QualType RetType,
Action::OwningStmtResult
Sema::ActOnReturnStmt(SourceLocation ReturnLoc, FullExprArg rex) {
bool RetValExprIsValid = !rex->isInvalid();
Expr *RetValExp = rex->takeAs<Expr>();
if (CurBlock)
return ActOnBlockReturnStmt(ReturnLoc, RetValExp);

View File

@@ -0,0 +1,18 @@
// RUN: clang-cc -fsyntax-only -verify %s
int x;
void f()
{
static int s;
int x; // expected-note{{'x' declared here}}
extern int g();
struct local {
int g() { return x; } // expected-error{{reference to local variable 'x' declared in enclosed function 'f'}}
int h() { return s; }
int k() { return :: x; }
int l() { return g(); }
};
}
local* p = 0; // expected-error{{unknown type name 'local'}}

View File

@@ -0,0 +1,30 @@
// RUN: clang-cc -fsyntax-only -verify %s
void f1() {
struct X {
struct Y;
};
struct X::Y {
void f() {}
};
}
void f2() {
struct X {
struct Y;
struct Y {
void f() {}
};
};
}
// A class nested within a local class is a local class.
void f3(int a) { // expected-note{{'a' declared here}}
struct X {
struct Y {
int f() { return a; } // expected-error{{reference to local variable 'a' declared in enclosed function 'f3'}}
};
};
}