[cfe-commits] r39194 - in /cfe/cfe/trunk: AST/Sema.cpp AST/Sema.h AST/SemaDecl.cpp AST/SemaExpr.cpp Parse/ParseExpr.cpp Sema/Sema.cpp Sema/Sema.h Sema/SemaDecl.cpp Sema/SemaExpr.cpp include/clang/Basic/DiagnosticKinds.def include/clang/Parse/Action.h

sabre at cs.uiuc.edu sabre at cs.uiuc.edu
Wed Jul 11 09:40:56 PDT 2007


Author: sabre
Date: Wed Jul 11 11:40:56 2007
New Revision: 39194

URL: http://llvm.org/viewvc/llvm-project?rev=39194&view=rev
Log:
Add support for C90 implicitly defined functions, e.g.:
int A() {
  return X();
}

Modified:
    cfe/cfe/trunk/AST/Sema.cpp
    cfe/cfe/trunk/AST/Sema.h
    cfe/cfe/trunk/AST/SemaDecl.cpp
    cfe/cfe/trunk/AST/SemaExpr.cpp
    cfe/cfe/trunk/Parse/ParseExpr.cpp
    cfe/cfe/trunk/Sema/Sema.cpp
    cfe/cfe/trunk/Sema/Sema.h
    cfe/cfe/trunk/Sema/SemaDecl.cpp
    cfe/cfe/trunk/Sema/SemaExpr.cpp
    cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/cfe/trunk/include/clang/Parse/Action.h

Modified: cfe/cfe/trunk/AST/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Sema.cpp?rev=39194&r1=39193&r2=39194&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/Sema.cpp (original)
+++ cfe/cfe/trunk/AST/Sema.cpp Wed Jul 11 11:40:56 2007
@@ -27,4 +27,6 @@
   Context.PP.Diag(Loc, DiagID, Msg);
 }
 
-
+const LangOptions &Sema::getLangOptions() const {
+  return Context.PP.getLangOptions();
+}

Modified: cfe/cfe/trunk/AST/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Sema.h?rev=39194&r1=39193&r2=39194&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/Sema.h (original)
+++ cfe/cfe/trunk/AST/Sema.h Wed Jul 11 11:40:56 2007
@@ -25,6 +25,7 @@
   class Preprocessor;
   class Decl;
   class TypeRef;
+  class LangOptions;
   
 /// Sema - This implements semantic analysis and AST building for C.
 class Sema : public Action {
@@ -40,6 +41,8 @@
     : Context(ctx), LastInGroupList(prevInGroup) {
   }
   
+  const LangOptions &getLangOptions() const;
+  
   void Diag(SourceLocation Loc, unsigned DiagID,
             const std::string &Msg = std::string());
   
@@ -66,6 +69,8 @@
   /// no declarator (e.g. "struct foo;") is parsed.
   virtual DeclTy *ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS);  
   
+  Decl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
+                                 Scope *S);
   
   //===--------------------------------------------------------------------===//
   // Statement Parsing Callbacks: SemaStmt.cpp.
@@ -113,8 +118,9 @@
   // Expression Parsing Callbacks: SemaExpr.cpp.
 
   // Primary Expressions.
-  virtual ExprResult ParseIdentifierExpr(SourceLocation Loc,
-                                         IdentifierInfo &II);
+  virtual ExprResult ParseIdentifierExpr(Scope *S, SourceLocation Loc,
+                                         IdentifierInfo &II,
+                                         bool HasTrailingLParen);
   virtual ExprResult ParseSimplePrimaryExpr(SourceLocation Loc,
                                             tok::TokenKind Kind);
   virtual ExprResult ParseIntegerConstant(SourceLocation Loc);

Modified: cfe/cfe/trunk/AST/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/SemaDecl.cpp?rev=39194&r1=39193&r2=39194&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/AST/SemaDecl.cpp Wed Jul 11 11:40:56 2007
@@ -17,6 +17,7 @@
 #include "clang/Parse/DeclSpec.h"
 #include "clang/Parse/Scope.h"
 #include "clang/Lex/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
 using namespace llvm;
 using namespace clang;
 
@@ -104,6 +105,33 @@
   return FD;
 }
 
+/// ImplicitlyDefineFunction - An undeclared identifier was used in a function
+/// call, forming a call to an implicitly defined function (per C99 6.5.1p2).
+Decl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
+                                     Scope *S) {
+  if (getLangOptions().C99)  // Extension in C99.
+    Diag(Loc, diag::ext_implicit_function_decl, II.getName());
+  else  // Legal in C90, but warn about it.
+    Diag(Loc, diag::warn_implicit_function_decl, II.getName());
+  
+  // FIXME: handle stuff like:
+  // void foo() { extern float X(); }
+  // void bar() { X(); }  <-- implicit decl for X in another scope.
+
+  // Set a Declarator for the implicit definition: int foo();
+  DeclSpec DS;
+  DS.TypeSpecType = DeclSpec::TST_int;
+  Declarator D(DS, Declarator::BlockContext);
+  D.AddTypeInfo(DeclaratorTypeInfo::getFunction(false, false, true, Loc));
+  D.SetIdentifier(&II, Loc);
+  
+  Decl *Result = static_cast<Decl*>(ParseDeclarator(S, D, 0, 0));
+  
+  // Visit this implicit declaration like any other top-level form.
+  LastInGroupList.push_back(Result);
+  return Result;
+}
+
 
 Decl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, Decl *PrevDecl) {
   assert(D.getIdentifier() && "Wrong callback for declspec withotu declarator");

Modified: cfe/cfe/trunk/AST/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/SemaExpr.cpp?rev=39194&r1=39193&r2=39194&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/AST/SemaExpr.cpp Wed Jul 11 11:40:56 2007
@@ -17,6 +17,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LangOptions.h"
 #include "clang/Basic/TargetInfo.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
@@ -239,13 +240,31 @@
 }
 
 
-Sema::ExprResult Sema::ParseIdentifierExpr(SourceLocation Loc,
-                                           IdentifierInfo &II) {
+/// ParseIdentifierExpr - The parser read an identifier in expression context,
+/// validate it per-C99 6.5.1.  HasTrailingLParen indicates whether this
+/// identifier is used in an function call context.
+Sema::ExprResult Sema::ParseIdentifierExpr(Scope *S, SourceLocation Loc,
+                                           IdentifierInfo &II,
+                                           bool HasTrailingLParen) {
   // Could be enum-constant or decl.
   Decl *D = II.getFETokenInfo<Decl>();
   if (D == 0) {
-    Diag(Loc, diag::err_undeclared_var_use, II.getName());
-    return true;
+    // FIXME: check to see if this is a use of a builtin.  By handling builtins
+    // here, we can avoid having to preload tons of decls for functions.
+
+    
+    // Otherwise, this is an imlicitly declared function reference (legal in
+    // C90, extension in C99).
+    if (HasTrailingLParen &&
+        // Not in C++.
+        !getLangOptions().CPlusPlus) {
+      D = ImplicitlyDefineFunction(Loc, II, S);
+    } else {
+      // If this name wasn't predeclared and if this is not a function call,
+      // diagnose the problem.
+      Diag(Loc, diag::err_undeclared_var_use, II.getName());
+      return true;
+    }
   }
   
   if (isa<TypeDecl>(D)) {

Modified: cfe/cfe/trunk/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Parse/ParseExpr.cpp?rev=39194&r1=39193&r2=39194&view=diff

==============================================================================
--- cfe/cfe/trunk/Parse/ParseExpr.cpp (original)
+++ cfe/cfe/trunk/Parse/ParseExpr.cpp Wed Jul 11 11:40:56 2007
@@ -201,8 +201,9 @@
   //   primary-expression: identifier
   
   // Let the actions module handle the identifier.
-  ExprResult Res = Actions.ParseIdentifierExpr(Tok.getLocation(),
-                                               *Tok.getIdentifierInfo());
+  ExprResult Res = Actions.ParseIdentifierExpr(CurScope, Tok.getLocation(),
+                                               *Tok.getIdentifierInfo(),
+                                               Tok.getKind() == tok::l_paren);
   
   // Because we have to parse an entire cast-expression before starting the
   // ParseRHSOfBinaryExpression method (which parses any trailing binops), we
@@ -231,8 +232,9 @@
   //   primary-expression: identifier
   
   // Let the actions module handle the identifier.
-  ExprResult Res = Actions.ParseIdentifierExpr(Tok.getLocation(),
-                                               *Tok.getIdentifierInfo());
+  ExprResult Res = Actions.ParseIdentifierExpr(CurScope, Tok.getLocation(),
+                                               *Tok.getIdentifierInfo(),
+                                               Tok.getKind() == tok::l_paren);
   
   // Because we have to parse an entire cast-expression before starting the
   // ParseRHSOfBinaryExpression method (which parses any trailing binops), we
@@ -479,13 +481,19 @@
     // These can be followed by postfix-expr pieces.
     return ParsePostfixExpressionSuffix(Res);
 
-  case tok::identifier:        // primary-expression: identifier
+  case tok::identifier: {      // primary-expression: identifier
                                // constant: enumeration-constant
-    Res = Actions.ParseIdentifierExpr(Tok.getLocation(),
-                                      *Tok.getIdentifierInfo());
-    ConsumeToken();
+    // Consume the identifier so that we can see if it is followed by a '('.
+    // Function designators are allowed to be undeclared (C99 6.5.1p2), so we
+    // need to know whether or not this identifier is a function designator or
+    // not.
+    IdentifierInfo &II = *Tok.getIdentifierInfo();
+    SourceLocation L = ConsumeToken();
+    Res = Actions.ParseIdentifierExpr(CurScope, L, II,
+                                      Tok.getKind() == tok::l_paren);
     // These can be followed by postfix-expr pieces.
     return ParsePostfixExpressionSuffix(Res);
+  }
   case tok::char_constant:     // constant: character-constant
   case tok::kw___func__:       // primary-expression: __func__ [C99 6.4.2.2]
   case tok::kw___FUNCTION__:   // primary-expression: __FUNCTION__ [GNU]

Modified: cfe/cfe/trunk/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/Sema.cpp?rev=39194&r1=39193&r2=39194&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/Sema.cpp (original)
+++ cfe/cfe/trunk/Sema/Sema.cpp Wed Jul 11 11:40:56 2007
@@ -27,4 +27,6 @@
   Context.PP.Diag(Loc, DiagID, Msg);
 }
 
-
+const LangOptions &Sema::getLangOptions() const {
+  return Context.PP.getLangOptions();
+}

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

==============================================================================
--- cfe/cfe/trunk/Sema/Sema.h (original)
+++ cfe/cfe/trunk/Sema/Sema.h Wed Jul 11 11:40:56 2007
@@ -25,6 +25,7 @@
   class Preprocessor;
   class Decl;
   class TypeRef;
+  class LangOptions;
   
 /// Sema - This implements semantic analysis and AST building for C.
 class Sema : public Action {
@@ -40,6 +41,8 @@
     : Context(ctx), LastInGroupList(prevInGroup) {
   }
   
+  const LangOptions &getLangOptions() const;
+  
   void Diag(SourceLocation Loc, unsigned DiagID,
             const std::string &Msg = std::string());
   
@@ -66,6 +69,8 @@
   /// no declarator (e.g. "struct foo;") is parsed.
   virtual DeclTy *ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS);  
   
+  Decl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
+                                 Scope *S);
   
   //===--------------------------------------------------------------------===//
   // Statement Parsing Callbacks: SemaStmt.cpp.
@@ -113,8 +118,9 @@
   // Expression Parsing Callbacks: SemaExpr.cpp.
 
   // Primary Expressions.
-  virtual ExprResult ParseIdentifierExpr(SourceLocation Loc,
-                                         IdentifierInfo &II);
+  virtual ExprResult ParseIdentifierExpr(Scope *S, SourceLocation Loc,
+                                         IdentifierInfo &II,
+                                         bool HasTrailingLParen);
   virtual ExprResult ParseSimplePrimaryExpr(SourceLocation Loc,
                                             tok::TokenKind Kind);
   virtual ExprResult ParseIntegerConstant(SourceLocation Loc);

Modified: cfe/cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaDecl.cpp?rev=39194&r1=39193&r2=39194&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaDecl.cpp Wed Jul 11 11:40:56 2007
@@ -17,6 +17,7 @@
 #include "clang/Parse/DeclSpec.h"
 #include "clang/Parse/Scope.h"
 #include "clang/Lex/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
 using namespace llvm;
 using namespace clang;
 
@@ -104,6 +105,33 @@
   return FD;
 }
 
+/// ImplicitlyDefineFunction - An undeclared identifier was used in a function
+/// call, forming a call to an implicitly defined function (per C99 6.5.1p2).
+Decl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
+                                     Scope *S) {
+  if (getLangOptions().C99)  // Extension in C99.
+    Diag(Loc, diag::ext_implicit_function_decl, II.getName());
+  else  // Legal in C90, but warn about it.
+    Diag(Loc, diag::warn_implicit_function_decl, II.getName());
+  
+  // FIXME: handle stuff like:
+  // void foo() { extern float X(); }
+  // void bar() { X(); }  <-- implicit decl for X in another scope.
+
+  // Set a Declarator for the implicit definition: int foo();
+  DeclSpec DS;
+  DS.TypeSpecType = DeclSpec::TST_int;
+  Declarator D(DS, Declarator::BlockContext);
+  D.AddTypeInfo(DeclaratorTypeInfo::getFunction(false, false, true, Loc));
+  D.SetIdentifier(&II, Loc);
+  
+  Decl *Result = static_cast<Decl*>(ParseDeclarator(S, D, 0, 0));
+  
+  // Visit this implicit declaration like any other top-level form.
+  LastInGroupList.push_back(Result);
+  return Result;
+}
+
 
 Decl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, Decl *PrevDecl) {
   assert(D.getIdentifier() && "Wrong callback for declspec withotu declarator");

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

==============================================================================
--- cfe/cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaExpr.cpp Wed Jul 11 11:40:56 2007
@@ -17,6 +17,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LangOptions.h"
 #include "clang/Basic/TargetInfo.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
@@ -239,13 +240,31 @@
 }
 
 
-Sema::ExprResult Sema::ParseIdentifierExpr(SourceLocation Loc,
-                                           IdentifierInfo &II) {
+/// ParseIdentifierExpr - The parser read an identifier in expression context,
+/// validate it per-C99 6.5.1.  HasTrailingLParen indicates whether this
+/// identifier is used in an function call context.
+Sema::ExprResult Sema::ParseIdentifierExpr(Scope *S, SourceLocation Loc,
+                                           IdentifierInfo &II,
+                                           bool HasTrailingLParen) {
   // Could be enum-constant or decl.
   Decl *D = II.getFETokenInfo<Decl>();
   if (D == 0) {
-    Diag(Loc, diag::err_undeclared_var_use, II.getName());
-    return true;
+    // FIXME: check to see if this is a use of a builtin.  By handling builtins
+    // here, we can avoid having to preload tons of decls for functions.
+
+    
+    // Otherwise, this is an imlicitly declared function reference (legal in
+    // C90, extension in C99).
+    if (HasTrailingLParen &&
+        // Not in C++.
+        !getLangOptions().CPlusPlus) {
+      D = ImplicitlyDefineFunction(Loc, II, S);
+    } else {
+      // If this name wasn't predeclared and if this is not a function call,
+      // diagnose the problem.
+      Diag(Loc, diag::err_undeclared_var_use, II.getName());
+      return true;
+    }
   }
   
   if (isa<TypeDecl>(D)) {

Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=39194&r1=39193&r2=39194&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:40:56 2007
@@ -392,7 +392,12 @@
 DIAG(err_unexpected_typedef, ERROR,
      "unexpected type name '%s': expected expression")
 DIAG(err_undeclared_var_use, ERROR,
-     "use of undeclared '%s' value")
+     "use of undeclared identifier '%s'")
+
+DIAG(warn_implicit_function_decl, WARNING,
+     "implicit declaration of function '%s'")
+DIAG(ext_implicit_function_decl, EXTENSION,
+     "implicit declaration of function '%s' is invalid in C99")
 
 DIAG(err_continue_not_in_loop, ERROR,
      "'continue' statement not in loop statement")

Modified: cfe/cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Parse/Action.h?rev=39194&r1=39193&r2=39194&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/Action.h Wed Jul 11 11:40:56 2007
@@ -211,8 +211,13 @@
   //===--------------------------------------------------------------------===//
   
   // Primary Expressions.
-  virtual ExprResult ParseIdentifierExpr(SourceLocation Loc,
-                                         IdentifierInfo &II) {
+  
+  /// ParseIdentifierExpr - Parse an identifier in expression context.
+  /// 'HasTrailingLParen' indicates whether or not the identifier has a '('
+  /// token immediately after it.
+  virtual ExprResult ParseIdentifierExpr(Scope *S, SourceLocation Loc,
+                                         IdentifierInfo &II,
+                                         bool HasTrailingLParen) {
     return 0;
   }
   





More information about the cfe-commits mailing list