[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