[cfe-commits] r77089 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/Type.h lib/AST/ASTContext.cpp lib/AST/Type.cpp lib/Analysis/CFG.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaType.cpp test/CodeGen/array.c test/Sema/return.c

Fariborz Jahanian fjahanian at apple.com
Sat Jul 25 14:56:39 PDT 2009


On Jul 25, 2009, at 2:26 PM, Mike Stump wrote:

> Author: mrs
> Date: Sat Jul 25 16:26:53 2009
> New Revision: 77089
>
> URL: http://llvm.org/viewvc/llvm-project?rev=77089&view=rev
> Log:
> Add noreturn as a type attribute, handle printing for them and handle
> calls to noreturn function pointers when CFG building.
>
> Modified:
>    cfe/trunk/include/clang/AST/ASTContext.h
>    cfe/trunk/include/clang/AST/Type.h
>    cfe/trunk/lib/AST/ASTContext.cpp
>    cfe/trunk/lib/AST/Type.cpp
>    cfe/trunk/lib/Analysis/CFG.cpp
>    cfe/trunk/lib/Sema/SemaDecl.cpp
>    cfe/trunk/lib/Sema/SemaType.cpp
>    cfe/trunk/test/CodeGen/array.c
>    cfe/trunk/test/Sema/return.c

Nice. Couple of comments below.

- Fariborz

>
>
> Modified: cfe/trunk/include/clang/AST/ASTContext.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=77089&r1=77088&r2=77089&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- cfe/trunk/include/clang/AST/ASTContext.h (original)
> +++ cfe/trunk/include/clang/AST/ASTContext.h Sat Jul 25 16:26:53 2009
> @@ -135,7 +135,7 @@
>   /// Since so few decls have attrs, we keep them in a hash map  
> instead of
>   /// wasting space in the Decl class.
>   llvm::DenseMap<const Decl*, Attr*> DeclAttrs;
> -
> +
>   /// \brief Keeps track of the static data member templates from  
> which
>   /// static data members of class template specializations were  
> instantiated.
>   ///
> @@ -218,7 +218,7 @@
>
>   /// \brief Erase the attributes corresponding to the given  
> declaration.
>   void eraseDeclAttrs(const Decl *D) { DeclAttrs.erase(D); }
> -
> +
>   /// \brief If this variable is an instantiated static data member  
> of a
>   /// class template specialization, returns the templated static  
> data member
>   /// from which it was instantiated.
> @@ -287,6 +287,10 @@
>   /// from T and the gc attribute.
>   QualType getObjCGCQualType(QualType T, QualType::GCAttrTypes  
> gcAttr);
>
> +  /// getNoReturnType - Add the noreturn attribute to the given  
> type which must
> +  /// be a FunctionType or a pointer to an allowable type or a  
> BlockPointer.
> +  QualType getNoReturnType(QualType T);
> +
>   /// getComplexType - Return the uniqued reference to the type for  
> a complex
>   /// number with the specified element type.
>   QualType getComplexType(QualType T);
> @@ -375,7 +379,7 @@
>
>   /// getFunctionNoProtoType - Return a K&R style C function type  
> like 'int()'.
>   ///
> -  QualType getFunctionNoProtoType(QualType ResultTy);
> +  QualType getFunctionNoProtoType(QualType ResultTy, bool NoReturn  
> = false);
>
>   /// getFunctionType - Return a normal function type with a typed  
> argument
>   /// list.  isVariadic indicates whether the argument list includes  
> '...'.
> @@ -383,7 +387,8 @@
>                            unsigned NumArgs, bool isVariadic,
>                            unsigned TypeQuals, bool hasExceptionSpec  
> = false,
>                            bool hasAnyExceptionSpec = false,
> -                           unsigned NumExs = 0, const QualType  
> *ExArray = 0);
> +                           unsigned NumExs = 0, const QualType  
> *ExArray = 0,
> +                           bool NoReturn = false);
>
>   /// getTypeDeclType - Return the unique reference to the type for
>   /// the specified type declaration.
>
> Modified: cfe/trunk/include/clang/AST/Type.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=77089&r1=77088&r2=77089&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/include/clang/AST/Type.h (original)
> +++ cfe/trunk/include/clang/AST/Type.h Sat Jul 25 16:26:53 2009
> @@ -215,6 +215,9 @@
>   bool isObjCGCStrong() const {
>     return getObjCGCAttr() == Strong;
>   }
> +
> +  /// getNoReturnAttr() - Return the noreturn attribute of this type.

Since functions returns bool, comment is confusing.
Maybe,  return 'true' if type has noreturn attribute; false, otherwise.

>
> +  bool getNoReturnAttr() const;
> };
>
> } // end clang.
> @@ -545,7 +548,7 @@
>   Type *getBaseType() const { return BaseType; }
>   QualType::GCAttrTypes getObjCGCAttr() const { return GCAttrType; }
>   unsigned getAddressSpace() const { return AddressSpace; }
> -
> +
>   virtual void getAsStringInternal(std::string &InnerString,
>                                    const PrintingPolicy &Policy)  
> const;
>
> @@ -1344,19 +1347,25 @@
>   /// cv-qualifier-seq, [...], are part of the function type.
>   ///
>   unsigned TypeQuals : 3;
> +
> +  /// NoReturn - Indicates if the function type is attribute  
> noreturn.
> +  unsigned NoReturn : 1;
>
>   // The type returned by the function.
>   QualType ResultType;
> protected:
>   FunctionType(TypeClass tc, QualType res, bool SubclassInfo,
> -               unsigned typeQuals, QualType Canonical, bool  
> Dependent)
> +               unsigned typeQuals, QualType Canonical, bool  
> Dependent,
> +               bool noReturn = false)
>     : Type(tc, Canonical, Dependent),
> -      SubClassData(SubclassInfo), TypeQuals(typeQuals),  
> ResultType(res) {}
> +      SubClassData(SubclassInfo), TypeQuals(typeQuals),  
> NoReturn(noReturn),
> +      ResultType(res) {}
>   bool getSubClassData() const { return SubClassData; }
>   unsigned getTypeQuals() const { return TypeQuals; }
> public:
>
>   QualType getResultType() const { return ResultType; }
> +  bool getNoReturnAttr() const { return NoReturn; }
>
>
>   static bool classof(const Type *T) {
> @@ -1369,9 +1378,10 @@
> /// FunctionNoProtoType - Represents a K&R-style 'int foo()'  
> function, which has
> /// no information available about its arguments.
> class FunctionNoProtoType : public FunctionType, public  
> llvm::FoldingSetNode {
> -  FunctionNoProtoType(QualType Result, QualType Canonical)
> +  FunctionNoProtoType(QualType Result, QualType Canonical,
> +                      bool NoReturn = false)
>     : FunctionType(FunctionNoProto, Result, false, 0, Canonical,
> -                   /*Dependent=*/false) {}
> +                   /*Dependent=*/false, NoReturn) {}
>   friend class ASTContext;  // ASTContext creates these.
> public:
>   // No additional state past what FunctionType provides.
> @@ -1380,9 +1390,11 @@
>                                    const PrintingPolicy &Policy)  
> const;
>
>   void Profile(llvm::FoldingSetNodeID &ID) {
> -    Profile(ID, getResultType());
> +    Profile(ID, getResultType(), getNoReturnAttr());
>   }
> -  static void Profile(llvm::FoldingSetNodeID &ID, QualType  
> ResultType) {
> +  static void Profile(llvm::FoldingSetNodeID &ID, QualType  
> ResultType,
> +                      bool NoReturn) {
> +    ID.AddInteger(NoReturn);
>     ID.AddPointer(ResultType.getAsOpaquePtr());
>   }
>
> @@ -1411,10 +1423,10 @@
>   FunctionProtoType(QualType Result, const QualType *ArgArray,  
> unsigned numArgs,
>                     bool isVariadic, unsigned typeQuals, bool hasExs,
>                     bool hasAnyExs, const QualType *ExArray,
> -                    unsigned numExs, QualType Canonical)
> +                    unsigned numExs, QualType Canonical, bool  
> NoReturn)
>     : FunctionType(FunctionProto, Result, isVariadic, typeQuals,  
> Canonical,
>                    (Result->isDependentType() ||
> -                    hasAnyDependentType(ArgArray, numArgs))),
> +                    hasAnyDependentType(ArgArray, numArgs)),  
> NoReturn),
>       NumArgs(numArgs), NumExceptions(numExs),  
> HasExceptionSpec(hasExs),
>       AnyExceptionSpec(hasAnyExs) {
>     // Fill in the trailing argument array.
> @@ -1497,7 +1509,8 @@
>                       arg_type_iterator ArgTys, unsigned NumArgs,
>                       bool isVariadic, unsigned TypeQuals,
>                       bool hasExceptionSpec, bool anyExceptionSpec,
> -                      unsigned NumExceptions, exception_iterator  
> Exs);
> +                      unsigned NumExceptions, exception_iterator Exs,
> +                      bool NoReturn);
> };
>
>
> @@ -2068,6 +2081,18 @@
>     return PT->getPointeeType().getObjCGCAttr();
>   return GCNone;
> }
> +
> +/// getNoReturnAttr - Return the noreturn attribute of this type.

See above comment.

>
> +inline bool QualType::getNoReturnAttr() const {
> +  QualType CT = getTypePtr()->getCanonicalTypeInternal();
> +  if (const PointerType *PT = getTypePtr()->getAsPointerType()) {
> +    if (const FunctionType *FT = PT->getPointeeType()- 
> >getAsFunctionType())
> +      return FT->getNoReturnAttr();
> +  } else if (const FunctionType *FT = getTypePtr()- 
> >getAsFunctionType())
> +    return FT->getNoReturnAttr();
> +
> +  return false;
> +}
>
> /// isMoreQualifiedThan - Determine whether this type is more
> /// qualified than the Other type. For example, "const volatile int"
>
> Modified: cfe/trunk/lib/AST/ASTContext.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=77089&r1=77088&r2=77089&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/AST/ASTContext.cpp (original)
> +++ cfe/trunk/lib/AST/ASTContext.cpp Sat Jul 25 16:26:53 2009
> @@ -965,7 +965,7 @@
>
>   // Check if we've already instantiated this type.
>   llvm::FoldingSetNodeID ID;
> -  ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);
> +  ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);
>   void *InsertPos = 0;
>   if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID,  
> InsertPos))
>     return QualType(EXTQy, CVRQuals);
> @@ -1007,17 +1007,17 @@
>   unsigned AddressSpace = 0;
>
>   if (ExtQualType *EQT = dyn_cast<ExtQualType>(TypeNode)) {
> -    // If this type already has an address space specified, it  
> cannot get
> +    // If this type already has an ObjCGC specified, it cannot get
>     // another one.
>     assert(EQT->getObjCGCAttr() == QualType::GCNone &&
> -           "Type cannot be in multiple addr spaces!");
> +           "Type cannot have multiple ObjCGCs!");

Thanks for fixing the comments  (my bad).

>
>     AddressSpace = EQT->getAddressSpace();
>     TypeNode = EQT->getBaseType();
>   }
>
>   // Check if we've already instantiated an gc qual'd type of this  
> type.
>   llvm::FoldingSetNodeID ID;
> -  ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);
> +  ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);
>   void *InsertPos = 0;
>   if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID,  
> InsertPos))
>     return QualType(EXTQy, CVRQuals);
> @@ -1041,6 +1041,30 @@
>   return QualType(New, CVRQuals);
> }
>
> +QualType ASTContext::getNoReturnType(QualType T) {
> +  if (T->isPointerType()) {
> +    QualType Pointee = T->getAsPointerType()->getPointeeType();
> +    QualType ResultType = getNoReturnType(Pointee);
> +    return getPointerType(ResultType);
> +  }
> +  if (T->isBlockPointerType()) {
> +    QualType Pointee = T->getAsBlockPointerType()->getPointeeType();
> +    QualType ResultType = getNoReturnType(Pointee);
> +    return getBlockPointerType(ResultType);
> +  }
> +  if (!T->isFunctionType())
> +    assert(0 && "can't noreturn qualify non-pointer to function or  
> block type");
> +
> +  if (const FunctionNoProtoType *F =  
> dyn_cast<FunctionNoProtoType>(T)) {
> +    return getFunctionNoProtoType(F->getResultType(), true);
> +  }
> +  const FunctionProtoType *F = cast<FunctionProtoType>(T);
> +  return getFunctionType(F->getResultType(), F->arg_type_begin(),
> +                         F->getNumArgs(), F->isVariadic(), F- 
> >getTypeQuals(),
> +                         F->hasExceptionSpec(), F- 
> >hasAnyExceptionSpec(),
> +                         F->getNumExceptions(), F- 
> >exception_begin(), true);
> +}

This function does not preserve the other attributes. For example,   
block pointers can be __weak/__strong.
See ASTContext::getObjCGCQualType.

>
> +
> /// getComplexType - Return the uniqued reference to the type for a  
> complex
> /// number with the specified element type.
> QualType ASTContext::getComplexType(QualType T) {
> @@ -1474,11 +1498,11 @@
>
> /// getFunctionNoProtoType - Return a K&R style C function type like  
> 'int()'.
> ///
> -QualType ASTContext::getFunctionNoProtoType(QualType ResultTy) {
> +QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool  
> NoReturn) {
>   // Unique functions, to guarantee there is only one function of a  
> particular
>   // structure.
>   llvm::FoldingSetNodeID ID;
> -  FunctionNoProtoType::Profile(ID, ResultTy);
> +  FunctionNoProtoType::Profile(ID, ResultTy, NoReturn);
>
>   void *InsertPos = 0;
>   if (FunctionNoProtoType *FT =
> @@ -1487,7 +1511,7 @@
>
>   QualType Canonical;
>   if (!ResultTy->isCanonical()) {
> -    Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy));
> +    Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy),  
> NoReturn);
>
>     // Get the new insert position for the node we care about.
>     FunctionNoProtoType *NewIP =
> @@ -1495,7 +1519,8 @@
>     assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP;
>   }
>
> -  FunctionNoProtoType *New =new(*this, 
> 8)FunctionNoProtoType(ResultTy,Canonical);
> +  FunctionNoProtoType *New
> +    = new (*this,8) FunctionNoProtoType(ResultTy, Canonical,  
> NoReturn);
>   Types.push_back(New);
>   FunctionNoProtoTypes.InsertNode(New, InsertPos);
>   return QualType(New, 0);
> @@ -1507,13 +1532,13 @@
>                                      unsigned NumArgs, bool  
> isVariadic,
>                                      unsigned TypeQuals, bool  
> hasExceptionSpec,
>                                      bool hasAnyExceptionSpec,  
> unsigned NumExs,
> -                                     const QualType *ExArray) {
> +                                     const QualType *ExArray, bool  
> NoReturn) {
>   // Unique functions, to guarantee there is only one function of a  
> particular
>   // structure.
>   llvm::FoldingSetNodeID ID;
>   FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs,  
> isVariadic,
>                              TypeQuals, hasExceptionSpec,  
> hasAnyExceptionSpec,
> -                             NumExs, ExArray);
> +                             NumExs, ExArray, NoReturn);
>
>   void *InsertPos = 0;
>   if (FunctionProtoType *FTP =
> @@ -1539,7 +1564,7 @@
>
>     Canonical = getFunctionType(getCanonicalType(ResultTy),
>                                 CanonicalArgs.data(), NumArgs,
> -                                isVariadic, TypeQuals);
> +                                isVariadic, TypeQuals, NoReturn);
>
>     // Get the new insert position for the node we care about.
>     FunctionProtoType *NewIP =
> @@ -1556,7 +1581,7 @@
>                                  NumExs*sizeof(QualType), 8);
>   new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, isVariadic,
>                               TypeQuals, hasExceptionSpec,  
> hasAnyExceptionSpec,
> -                              ExArray, NumExs, Canonical);
> +                              ExArray, NumExs, Canonical, NoReturn);
>   Types.push_back(FTP);
>   FunctionProtoTypes.InsertNode(FTP, InsertPos);
>   return QualType(FTP, 0);
> @@ -3344,7 +3369,12 @@
>     allLTypes = false;
>   if (getCanonicalType(retType) != getCanonicalType(rbase- 
> >getResultType()))
>     allRTypes = false;
> -
> +  bool NoReturn = lbase->getNoReturnAttr() || rbase- 
> >getNoReturnAttr();
> +  if (NoReturn != lbase->getNoReturnAttr())
> +    allLTypes = false;
> +  if (NoReturn != rbase->getNoReturnAttr())
> +    allRTypes = false;
> +
>   if (lproto && rproto) { // two C99 style function prototypes
>     assert(!lproto->hasExceptionSpec() && !rproto- 
> >hasExceptionSpec() &&
>            "C++ shouldn't be here");
> @@ -3378,7 +3408,8 @@
>     if (allLTypes) return lhs;
>     if (allRTypes) return rhs;
>     return getFunctionType(retType, types.begin(), types.size(),
> -                           lproto->isVariadic(), lproto- 
> >getTypeQuals());
> +                           lproto->isVariadic(), lproto- 
> >getTypeQuals(),
> +                           NoReturn);
>   }
>
>   if (lproto) allRTypes = false;
> @@ -3405,12 +3436,12 @@
>     if (allRTypes) return rhs;
>     return getFunctionType(retType, proto->arg_type_begin(),
>                            proto->getNumArgs(), lproto->isVariadic(),
> -                           lproto->getTypeQuals());
> +                           lproto->getTypeQuals(), NoReturn);
>   }
>
>   if (allLTypes) return lhs;
>   if (allRTypes) return rhs;
> -  return getFunctionNoProtoType(retType);
> +  return getFunctionNoProtoType(retType, NoReturn);
> }
>
> QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
>
> Modified: cfe/trunk/lib/AST/Type.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=77089&r1=77088&r2=77089&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/AST/Type.cpp (original)
> +++ cfe/trunk/lib/AST/Type.cpp Sat Jul 25 16:26:53 2009
> @@ -904,7 +904,7 @@
>                                 unsigned NumArgs, bool isVariadic,
>                                 unsigned TypeQuals, bool  
> hasExceptionSpec,
>                                 bool anyExceptionSpec, unsigned  
> NumExceptions,
> -                                exception_iterator Exs) {
> +                                exception_iterator Exs, bool  
> NoReturn) {
>   ID.AddPointer(Result.getAsOpaquePtr());
>   for (unsigned i = 0; i != NumArgs; ++i)
>     ID.AddPointer(ArgTys[i].getAsOpaquePtr());
> @@ -916,12 +916,13 @@
>     for(unsigned i = 0; i != NumExceptions; ++i)
>       ID.AddPointer(Exs[i].getAsOpaquePtr());
>   }
> +  ID.AddInteger(NoReturn);
> }
>
> void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID) {
>   Profile(ID, getResultType(), arg_type_begin(), NumArgs,  
> isVariadic(),
>           getTypeQuals(), hasExceptionSpec(), hasAnyExceptionSpec(),
> -          getNumExceptions(), exception_begin());
> +          getNumExceptions(), exception_begin(), getNoReturnAttr());
> }
>
> void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID,
> @@ -1082,7 +1083,7 @@
>     if (EQT->getObjCGCAttr())
>       GCAttrType = EQT->getObjCGCAttr();
>     return EQT->getBaseType();
> -  }else {
> +  } else {
>     // Use the sugared type unless desugaring found extra qualifiers.
>     return (DT.getCVRQualifiers() ? DT.getTypePtr() : T);
>   }
> @@ -1413,6 +1414,8 @@
>     S = "(" + S + ")";
>
>   S += "()";
> +  if (getNoReturnAttr())
> +    S += " __attribute__((noreturn))";
>   getResultType().getAsStringInternal(S, Policy);
> }
>
> @@ -1442,6 +1445,8 @@
>   }
>
>   S += ")";
> +  if (getNoReturnAttr())
> +    S += " __attribute__((noreturn))";
>   getResultType().getAsStringInternal(S, Policy);
> }
>
>
> Modified: cfe/trunk/lib/Analysis/CFG.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=77089&r1=77088&r2=77089&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Analysis/CFG.cpp (original)
> +++ cfe/trunk/lib/Analysis/CFG.cpp Sat Jul 25 16:26:53 2009
> @@ -501,25 +501,29 @@
>
> CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, bool alwaysAdd) {
>   // If this is a call to a no-return function, this stops the block  
> here.
> -  if (FunctionDecl *FD = C->getDirectCallee()) {
> -
> -    if (!FD->hasAttr<NoReturnAttr>())
> -      return VisitStmt(C, alwaysAdd);
> -
> -    if (Block && !FinishBlock(Block))
> -      return 0;
> -
> -    // Create new block with no successor for the remaining pieces.
> -    Block = createBlock(false);
> -    Block->appendStmt(C);
> +  bool NoReturn = false;
> +  if (C->getCallee()->getType().getNoReturnAttr()) {
> +    NoReturn = true;
> +  }
> +
> +  if (FunctionDecl *FD = C->getDirectCallee())
> +    if (FD->hasAttr<NoReturnAttr>())
> +      NoReturn = true;
> +
> +  if (!NoReturn)
> +    return VisitStmt(C, alwaysAdd);
>
> -    // Wire this to the exit block directly.
> -    Block->addSuccessor(&cfg->getExit());
> +  if (Block && !FinishBlock(Block))
> +    return 0;
>
> -    return VisitChildren(C);
> -  }
> +  // Create new block with no successor for the remaining pieces.
> +  Block = createBlock(false);
> +  Block->appendStmt(C);
> +
> +  // Wire this to the exit block directly.
> +  Block->addSuccessor(&cfg->getExit());
>
> -  return VisitStmt(C, alwaysAdd);
> +  return VisitChildren(C);
> }
>
> CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C) {
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=77089&r1=77088&r2=77089&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Jul 25 16:26:53 2009
> @@ -1084,7 +1084,10 @@
>     bool NoReturnEdge = false;
>     if (CallExpr *C = dyn_cast<CallExpr>(S)) {
>       Expr *CEE = C->getCallee()->IgnoreParenCasts();
> -      if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
> +      if (CEE->getType().getNoReturnAttr()) {
> +        NoReturnEdge = true;
> +        HasFakeEdge = true;
> +      } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
>         if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DRE- 
> >getDecl())) {
>           if (FD->hasAttr<NoReturnAttr>()) {
>             NoReturnEdge = true;
>
> Modified: cfe/trunk/lib/Sema/SemaType.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=77089&r1=77088&r2=77089&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Sema/SemaType.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaType.cpp Sat Jul 25 16:26:53 2009
> @@ -1506,6 +1506,22 @@
>   Type = S.Context.getObjCGCQualType(Type, GCAttr);
> }
>
> +/// HandleNoReturnTypeAttribute - Process the noreturn attribute on  
> the
> +/// specified type.  The attribute contains 0 arguments.
> +static void HandleNoReturnTypeAttribute(QualType &Type,
> +                                        const AttributeList &Attr,  
> Sema &S) {
> +  if (Attr.getNumArgs() != 0)
Don't you want to issue error here?
>
> +    return;
> +
> +  // We only apply this to a pointer to function or a pointer to  
> block.
> +  if (!Type->isFunctionPointerType()
> +      && !Type->isBlockPointerType()
> +      && !Type->isFunctionType())

And here?

>
> +    return;
> +
> +  Type = S.Context.getNoReturnType(Type);
> +}
> +
> void Sema::ProcessTypeAttributeList(QualType &Result, const  
> AttributeList *AL) {
>   // Scan through and apply attributes to this type where it makes  
> sense.  Some
>   // attributes (such as __address_space__, __vector_size__, etc)  
> apply to the
> @@ -1522,6 +1538,9 @@
>     case AttributeList::AT_objc_gc:
>       HandleObjCGCTypeAttribute(Result, *AL, *this);
>       break;
> +    case AttributeList::AT_noreturn:
> +      HandleNoReturnTypeAttribute(Result, *AL, *this);
> +      break;
>     }
>   }
> }
>
> Modified: cfe/trunk/test/CodeGen/array.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/array.c?rev=77089&r1=77088&r2=77089&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/test/CodeGen/array.c (original)
> +++ cfe/trunk/test/CodeGen/array.c Sat Jul 25 16:26:53 2009
> @@ -1,11 +1,11 @@
> // RUN: clang-cc -emit-llvm %s -o %t
>
> -int f() {
> +void f() {
>  int a[2];
>  a[0] = 0;
> }
>
> -int f2() {
> +void f2() {
>   int x = 0;
>   int y = 1;
>   int a[10] = { y, x, 2, 3};
>
> Modified: cfe/trunk/test/Sema/return.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/return.c?rev=77089&r1=77088&r2=77089&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/test/Sema/return.c (original)
> +++ cfe/trunk/test/Sema/return.c Sat Jul 25 16:26:53 2009
> @@ -158,6 +158,7 @@
> } // expected-warning {{control reaches end of non-void function}}
>
> int j;
> +void (*fptr)() __attribute__((noreturn));
> int test27() {
>   switch (j) {
>   case 1:
> @@ -178,6 +179,9 @@
>   case 5:
>     while (1) { return 1; }
>     break;
> +  case 6:
> +    fptr();
> +    break;
>   default:
>     return 1;
>   }
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits




More information about the cfe-commits mailing list