[cfe-commits] r74027 - in /cfe/trunk: clang.xcodeproj/ clang.xcodeproj/project.pbxproj include/clang/AST/DeclCXX.h include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaStmt.cpp test/CXX/class/class.local/p1.cpp test/CXX/class/class.local/p3.cpp

Anders Carlsson andersca at mac.com
Tue Jun 23 17:10:44 PDT 2009


Author: andersca
Date: Tue Jun 23 19:10:43 2009
New Revision: 74027

URL: http://llvm.org/viewvc/llvm-project?rev=74027&view=rev
Log:
[class.local] p1 and p3. Also, add back the xcodeproj file.

Added:
    cfe/trunk/clang.xcodeproj/   (props changed)
      - copied from r73959, cfe/trunk/clang.xcodeproj/
    cfe/trunk/clang.xcodeproj/project.pbxproj
      - copied unchanged from r73959, cfe/trunk/clang.xcodeproj/project.pbxproj
    cfe/trunk/test/CXX/class/class.local/p1.cpp
    cfe/trunk/test/CXX/class/class.local/p3.cpp
Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaStmt.cpp

Propchange: cfe/trunk/clang.xcodeproj/

------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Tue Jun 23 19:10:43 2009
@@ -0,0 +1,2 @@
+*.mode1
+*.pbxuser

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=74027&r1=74026&r2=74027&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Jun 23 19:10:43 2009
@@ -449,6 +449,15 @@
   /// 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.

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=74027&r1=74026&r2=74027&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Jun 23 19:10:43 2009
@@ -1603,6 +1603,12 @@
   "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">;

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=74027&r1=74026&r2=74027&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Jun 23 19:10:43 2009
@@ -1377,9 +1377,10 @@
                                                     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

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=74027&r1=74026&r2=74027&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Jun 23 19:10:43 2009
@@ -623,17 +623,36 @@
 /// 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 @@
         // 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 @@
 
   // 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 @@
       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 @@
     }
   }
 
-  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,

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=74027&r1=74026&r2=74027&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Tue Jun 23 19:10:43 2009
@@ -835,6 +835,7 @@
 
 Action::OwningStmtResult
 Sema::ActOnReturnStmt(SourceLocation ReturnLoc, FullExprArg rex) {
+  bool RetValExprIsValid = !rex->isInvalid();
   Expr *RetValExp = rex->takeAs<Expr>();
   if (CurBlock)
     return ActOnBlockReturnStmt(ReturnLoc, RetValExp);

Added: cfe/trunk/test/CXX/class/class.local/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.local/p1.cpp?rev=74027&view=auto

==============================================================================
--- cfe/trunk/test/CXX/class/class.local/p1.cpp (added)
+++ cfe/trunk/test/CXX/class/class.local/p1.cpp Tue Jun 23 19:10:43 2009
@@ -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'}}

Added: cfe/trunk/test/CXX/class/class.local/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.local/p3.cpp?rev=74027&view=auto

==============================================================================
--- cfe/trunk/test/CXX/class/class.local/p3.cpp (added)
+++ cfe/trunk/test/CXX/class/class.local/p3.cpp Tue Jun 23 19:10:43 2009
@@ -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'}}
+    };
+  };
+}
\ No newline at end of file





More information about the cfe-commits mailing list