[cfe-dev] Bug in clang parsing pointer to an array in function parameter list
Justin Handville
uniheliodem at gmail.com
Sun Sep 9 15:32:52 PDT 2007
With the following patch, I can now compile and execute this source file:
int puts(char*);
int main(int argc, char* argv[])
{
char* foo = argv[0];
puts(foo);
return 0;
}
Here's the patch. I'm curious to see if this will work in all cases.
I am still adding test cases to the build, so it is a bit
experimental:
ndex: CodeGen/CodeGenFunction.h
===================================================================
--- CodeGen/CodeGenFunction.h (revision 41790)
+++ CodeGen/CodeGenFunction.h (working copy)
@@ -237,6 +237,11 @@
};
llvm::SmallVector<BreakContinue, 8> BreakContinueStack;
+ static bool
+ isCompatibleDeclPointerType(
+ const llvm::Type* Arg,
+ const llvm::Type* DeclPtr);
+
public:
CodeGenFunction(CodeGenModule &cgm);
Index: CodeGen/CGDecl.cpp
===================================================================
--- CodeGen/CGDecl.cpp (revision 41790)
+++ CodeGen/CGDecl.cpp (working copy)
@@ -96,11 +96,69 @@
}
}
+bool
+CodeGenFunction::isCompatibleDeclPointerType(
+ const llvm::Type* ArgType,
+ const llvm::Type* DeclType)
+{
+ if(
+ ArgType->getTypeID() != llvm::Type::PointerTyID
+ || DeclType->getTypeID() != llvm::Type::PointerTyID)
+ {
+ return false;
+ }
+
+ while(
+ ArgType->getNumContainedTypes() == 1
+ && DeclType->getNumContainedTypes() == 1)
+ {
+ const llvm::Type* ArgContainedType = ArgType->getContainedType(0);
+ const llvm::Type* DeclContainedType = DeclType->getContainedType(0);
+
+ //if the two contained types point to the same
+ //location, then these pointer types are compatible
+ if(
+ ArgContainedType == DeclContainedType)
+ {
+ return true;
+ }
+ //is the pointer indirection level different?
+ else if(
+ ArgContainedType->getNumContainedTypes() !=
+ DeclContainedType->getNumContainedTypes())
+ {
+ break;
+ }
+ //are these compatible pointer / array types?
+ else if(
+ llvm::SequentialType::classof(ArgContainedType)
+ && llvm::SequentialType::classof(DeclContainedType))
+ {
+ if( ArgContainedType->getNumContainedTypes() != 1 )
+ {
+ //FIXME will this ever happen with arrays / pointers?
+ break;
+ }
+
+ ArgType = ArgContainedType;
+ DeclType = DeclContainedType;
+ }
+ else
+ {
+ //one or more of these is something other than an array / pointer
+ break;
+ }
+ }
+
+ return false;
+}
+
/// Emit an alloca for the specified parameter and set up LocalDeclMap.
void CodeGenFunction::EmitParmDecl(const ParmVarDecl &D, llvm::Value *Arg) {
QualType Ty = D.getCanonicalType();
llvm::Value *DeclPtr;
+
if (!Ty->isConstantSizeType(getContext())) {
// Variable sized values always are passed by-reference.
DeclPtr = Arg;
@@ -111,7 +169,19 @@
// TODO: Alignment
DeclPtr = new llvm::AllocaInst(LTy, 0, std::string(D.getName())+".addr",
AllocaInsertPt);
-
+
+ //do we need to perform an implicit conversion?
+ if( isCompatibleDeclPointerType(Arg->getType(), DeclPtr->getType()) )
+ {
+ llvm::Value* CastPtr =
+ Builder.CreateBitCast(
+ Arg,
+ LTy,
+ (std::string(D.getName()) + ".implconv").c_str());
+
+ Arg = CastPtr;
+ }
+
// Store the initial value into the alloca.
Builder.CreateStore(Arg, DeclPtr);
} else {
On 9/9/07, Justin Handville <uniheliodem at gmail.com> wrote:
> Perhaps the better question to ask is where should this transform occur?
>
> On 9/9/07, Justin Handville <uniheliodem at gmail.com> wrote:
> > The following code snippet generates an assert when compiled with
> > clang -emit-llvm
> >
> > int main(int argc, char* argv[])
> > {
> > return 0;
> > }
> >
> > Assert:
> >
> > Assertion failed: (getOperand(0)->getType() ==
> > cast<PointerType>(getOperand(1)->getType())->getElementType() && "Ptr
> > must be a pointer to Val type!"), function AssertOK, file
> > Instructions.cpp, line 796.
> >
> > The problem here is at line 116 of CGDecl.cpp:
> >
> > if (LTy->isFirstClassType()) {
> > // TODO: Alignment
> > DeclPtr = new llvm::AllocaInst(LTy, 0, std::string(D.getName())+".addr",
> > AllocaInsertPt);
> >
> > // Store the initial value into the alloca.
> > Builder.CreateStore(Arg, DeclPtr); //attempting to store
> > char*[] as char**
> >
> > The problem is that llvm treats char*[] and char** as two distinct
> > types as far as I can tell. EmitParmDecl should convert the type to a
> > char** before calling CreateStore, since this is how the argument
> > would be passed in C ABI.
> >
> > I assume that a transform step should be added before the CreateStore
> > that could normalize the argument to match the declptr. I assume a
> > good approach would be to descend through both Arg and DeclPtr,
> > transforming Arg to match DeclPtr where compatible, or raising an
> > appropriate diagnostic error if such a transformation is not possible.
> >
> > If I can get some approval that this route would work in this case,
> > then I will go ahead and submit the patch.
> >
> > Thanks,
> > Justin
> >
>
More information about the cfe-dev
mailing list