mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 12:26:52 +08:00
[class.local] p1 and p3. Also, add back the xcodeproj file.
llvm-svn: 74027
This commit is contained in:
1844
clang/clang.xcodeproj/project.pbxproj
Normal file
1844
clang/clang.xcodeproj/project.pbxproj
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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.
|
||||
|
||||
@@ -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">;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
18
clang/test/CXX/class/class.local/p1.cpp
Normal file
18
clang/test/CXX/class/class.local/p1.cpp
Normal 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'}}
|
||||
30
clang/test/CXX/class/class.local/p3.cpp
Normal file
30
clang/test/CXX/class/class.local/p3.cpp
Normal 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'}}
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user