[cfe-commits] r168895 - in /cfe/trunk: include/clang/Sema/Initialization.h lib/AST/ASTContext.cpp lib/CodeGen/CGCall.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp test/Sema/merge-decls.c

Rafael Espindola rafael.espindola at gmail.com
Thu Nov 29 08:09:03 PST 2012


Author: rafael
Date: Thu Nov 29 10:09:03 2012
New Revision: 168895

URL: http://llvm.org/viewvc/llvm-project?rev=168895&view=rev
Log:
Merge function types in C.

Among other differences, GCC accepts

  typedef int IA[];
  typedef int A10[10];
  static A10 *f(void);
  static IA  *f(void);
  void g(void) {
    (void)sizeof(*f());
  }

but clang used to reject it with:

  invalid application of 'sizeof' to an incomplete type 'IA' (aka 'int []')

The intention of c99's 6.2.7 seems to be that we should use the composite type
and accept as gcc does.

Doing the type merging required some extra fixes:
  * Use the type from the function type in initializations, even if an parameter
    is available.
  * Fix the merging of the noreturn attribute in function types.
  * Make CodeGen  handle the fact that an parameter type can be different from
    the corresponding type in the function type.

Modified:
    cfe/trunk/include/clang/Sema/Initialization.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/CodeGen/CGCall.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/Sema/merge-decls.c

Modified: cfe/trunk/include/clang/Sema/Initialization.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=168895&r1=168894&r2=168895&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Initialization.h (original)
+++ cfe/trunk/include/clang/Sema/Initialization.h Thu Nov 29 10:09:03 2012
@@ -172,17 +172,25 @@
   static InitializedEntity InitializeVariable(VarDecl *Var) {
     return InitializedEntity(Var);
   }
-  
+
   /// \brief Create the initialization entity for a parameter.
   static InitializedEntity InitializeParameter(ASTContext &Context,
                                                ParmVarDecl *Parm) {
+    return InitializeParameter(Context, Parm,
+                               Parm->getType().getUnqualifiedType());
+  }
+
+  /// \brief Create the initialization entity for a parameter, but use
+  /// another type.
+  static InitializedEntity InitializeParameter(ASTContext &Context,
+                                               ParmVarDecl *Parm,
+                                               QualType Type) {
     bool Consumed = (Context.getLangOpts().ObjCAutoRefCount &&
                      Parm->hasAttr<NSConsumedAttr>());
 
     InitializedEntity Entity;
     Entity.Kind = EK_Parameter;
-    Entity.Type = Context.getVariableArrayDecayedType(
-                                       Parm->getType().getUnqualifiedType());
+    Entity.Type = Context.getVariableArrayDecayedType(Type);
     Entity.Parent = 0;
     Entity.Parameter
       = (static_cast<uintptr_t>(Consumed) | reinterpret_cast<uintptr_t>(Parm));

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=168895&r1=168894&r2=168895&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Thu Nov 29 10:09:03 2012
@@ -6486,14 +6486,14 @@
   if (lbaseInfo.getProducesResult() != rbaseInfo.getProducesResult())
     return QualType();
 
-  // functypes which return are preferred over those that do not.
-  if (lbaseInfo.getNoReturn() && !rbaseInfo.getNoReturn())
-    allLTypes = false;
-  else if (!lbaseInfo.getNoReturn() && rbaseInfo.getNoReturn())
-    allRTypes = false;
   // FIXME: some uses, e.g. conditional exprs, really want this to be 'both'.
   bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn();
 
+  if (lbaseInfo.getNoReturn() != NoReturn)
+    allLTypes = false;
+  if (rbaseInfo.getNoReturn() != NoReturn)
+    allRTypes = false;
+
   FunctionType::ExtInfo einfo = lbaseInfo.withNoReturn(NoReturn);
 
   if (lproto && rproto) { // two C99 style function prototypes

Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=168895&r1=168894&r2=168895&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Thu Nov 29 10:09:03 2012
@@ -1232,7 +1232,15 @@
 
         if (isPromoted)
           V = emitArgumentDemotion(*this, Arg, V);
-        
+
+        // Because of merging of function types from multiple decls it is
+        // possible for the type of an argument to not match the corresponding
+        // type in the function type. Since we are codegening the callee
+        // in here, add a cast to the argument type.
+        llvm::Type *LTy = ConvertType(Arg->getType());
+        if (V->getType() != LTy)
+          V = Builder.CreateBitCast(V, LTy);
+
         EmitParmDecl(*Arg, V, ArgNo);
         break;
       }

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=168895&r1=168894&r2=168895&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Nov 29 10:09:03 2012
@@ -2402,6 +2402,12 @@
   if (getLangOpts().CPlusPlus)
     return MergeCXXFunctionDecl(New, Old, S);
 
+  // Merge the function types so the we get the composite types for the return
+  // and argument types.
+  QualType Merged = Context.mergeTypes(Old->getType(), New->getType());
+  if (!Merged.isNull())
+    New->setType(Merged);
+
   return false;
 }
 

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=168895&r1=168894&r2=168895&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Nov 29 10:09:03 2012
@@ -3730,10 +3730,10 @@
           (!Param || !Param->hasAttr<CFConsumedAttr>()))
         Arg = stripARCUnbridgedCast(Arg);
 
-      InitializedEntity Entity =
-        Param? InitializedEntity::InitializeParameter(Context, Param)
-             : InitializedEntity::InitializeParameter(Context, ProtoArgType,
-                                                      Proto->isArgConsumed(i));
+      InitializedEntity Entity = Param ?
+          InitializedEntity::InitializeParameter(Context, Param, ProtoArgType)
+        : InitializedEntity::InitializeParameter(Context, ProtoArgType,
+                                                 Proto->isArgConsumed(i));
       ExprResult ArgE = PerformCopyInitialization(Entity,
                                                   SourceLocation(),
                                                   Owned(Arg),

Modified: cfe/trunk/test/Sema/merge-decls.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/merge-decls.c?rev=168895&r1=168894&r2=168895&view=diff
==============================================================================
--- cfe/trunk/test/Sema/merge-decls.c (original)
+++ cfe/trunk/test/Sema/merge-decls.c Thu Nov 29 10:09:03 2012
@@ -48,3 +48,46 @@
   }
   (void)sizeof(*test1_f());
 }
+
+typedef int test2_IA[];
+typedef int test2_A10[10];
+
+static test2_A10 *test2_f(void);
+static test2_IA  *test2_f(void);
+
+void test2_g(void)
+{
+  (void)sizeof(*test2_f());
+}
+
+int (*test3_f())[10];
+int (*test3_f())[];
+int test3_k = sizeof(*test3_f());
+
+void test4_f(int);
+void test4_f(a)
+  char a;
+{
+  int v[sizeof(a) == 1 ? 1 : -1];
+}
+
+int test5_f(int (*)[10]);
+int test5_f(int (*x)[]) {
+  return sizeof(*x); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}}
+}
+
+void test6_f(int (*a)[11]);
+void test6_f(a)
+   int (*a)[];
+{}
+void test6_g() {
+  int arr[10];
+  test6_f(&arr); // expected-warning {{incompatible pointer types passing 'int (*)[10]' to parameter of type 'int (*)[11]}}
+}
+
+void test7_f(int (*)[10]);
+void test7_f(int (*)[]); // expected-note {{passing argument to parameter here}}
+void test7_g() {
+  int x[5];
+  test7_f(&x); // expected-warning {{incompatible pointer types passing 'int (*)[5]' to parameter of type 'int (*)[10]}}
+}





More information about the cfe-commits mailing list