[cfe-commits] r129554 - in /cfe/trunk: docs/ include/clang/AST/ include/clang/Basic/ include/clang/Parse/ include/clang/Sema/ include/clang/Serialization/ lib/AST/ lib/CodeGen/ lib/Lex/ lib/Parse/ lib/Sema/ lib/Serialization/ lib/StaticAnalyzer/Core/ test/PCH/ test/Parser/ test/Sema/ test/SemaCXX/ tools/libclang/

Peter Collingbourne peter at pcc.me.uk
Thu Apr 14 17:35:48 PDT 2011


Author: pcc
Date: Thu Apr 14 19:35:48 2011
New Revision: 129554

URL: http://llvm.org/viewvc/llvm-project?rev=129554&view=rev
Log:
C1X: implement generic selections

As an extension, generic selection support has been added for all
supported languages.  The syntax is the same as for C1X.

Added:
    cfe/trunk/test/Parser/c1x-generic-selection.c
    cfe/trunk/test/Sema/generic-selection.c
    cfe/trunk/test/SemaCXX/generic-selection.cpp
Modified:
    cfe/trunk/docs/LanguageExtensions.html
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/StmtNodes.td
    cfe/trunk/include/clang/Basic/TokenKinds.def
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/Ownership.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/ExprClassification.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/AST/StmtProfile.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprAgg.cpp
    cfe/trunk/lib/CodeGen/CGExprComplex.cpp
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/lib/Lex/PPMacroExpansion.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/test/PCH/exprs.c
    cfe/trunk/test/PCH/exprs.h
    cfe/trunk/tools/libclang/CXCursor.cpp

Modified: cfe/trunk/docs/LanguageExtensions.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.html?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/docs/LanguageExtensions.html (original)
+++ cfe/trunk/docs/LanguageExtensions.html Thu Apr 14 19:35:48 2011
@@ -52,6 +52,7 @@
 <li><a href="#checking_type_traits">Checks for Type Traits</a></li>
 <li><a href="#blocks">Blocks</a></li>
 <li><a href="#overloading-in-c">Function Overloading in C</a></li>
+<li><a href="#generic-selections">Generic Selections</a></li>
 <li><a href="#builtins">Builtin Functions</a>
   <ul>
   <li><a href="#__builtin_shufflevector">__builtin_shufflevector</a></li>
@@ -604,6 +605,20 @@
 
 
 <!-- ======================================================================= -->
+<h2 id="generic-selections">Generic Selections</h2>
+<!-- ======================================================================= -->
+
+<p>The C1X generic selection expression is available in all languages
+supported by Clang.  The syntax is the same as that given in the C1X draft
+standard.</p>
+
+<p>In C, type compatibility is decided according to the rules given in the
+appropriate standard, but in C++, which lacks the type compatibility rules
+used in C, types are considered compatible only if they are equivalent.</p>
+
+<p>Query for this feature with __has_feature(generic_selections).</p>
+
+<!-- ======================================================================= -->
 <h2 id="builtins">Builtin Functions</h2>
 <!-- ======================================================================= -->
 

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Thu Apr 14 19:35:48 2011
@@ -3679,6 +3679,118 @@
 };
 
 
+/// \brief Represents a C1X generic selection.
+///
+/// A generic selection (C1X 6.5.1.1) contains an unevaluated controlling
+/// expression, followed by one or more generic associations.  Each generic
+/// association specifies a type name and an expression, or "default" and an
+/// expression (in which case it is known as a default generic association).
+/// The type and value of the generic selection are identical to those of its
+/// result expression, which is defined as the expression in the generic
+/// association with a type name that is compatible with the type of the
+/// controlling expression, or the expression in the default generic association
+/// if no types are compatible.  For example:
+///
+/// @code
+/// _Generic(X, double: 1, float: 2, default: 3)
+/// @endcode
+///
+/// The above expression evaluates to 1 if 1.0 is substituted for X, 2 if 1.0f
+/// or 3 if "hello".
+///
+/// As an extension, generic selections are allowed in C++, where the following
+/// additional semantics apply:
+///
+/// Any generic selection whose controlling expression is type-dependent or
+/// which names a dependent type in its association list is result-dependent,
+/// which means that the choice of result expression is dependent.
+/// Result-dependent generic associations are both type- and value-dependent.
+class GenericSelectionExpr : public Expr {
+  enum { CONTROLLING, END_EXPR };
+  TypeSourceInfo **AssocTypes;
+  Stmt **SubExprs;
+  unsigned NumAssocs, ResultIndex;
+  SourceLocation GenericLoc, DefaultLoc, RParenLoc;
+
+public:
+  GenericSelectionExpr(ASTContext &Context,
+                       SourceLocation GenericLoc, Expr *ControllingExpr,
+                       TypeSourceInfo **AssocTypes, Expr **AssocExprs,
+                       unsigned NumAssocs, SourceLocation DefaultLoc,
+                       SourceLocation RParenLoc,
+                       bool ContainsUnexpandedParameterPack,
+                       unsigned ResultIndex);
+
+  /// This constructor is used in the result-dependent case.
+  GenericSelectionExpr(ASTContext &Context,
+                       SourceLocation GenericLoc, Expr *ControllingExpr,
+                       TypeSourceInfo **AssocTypes, Expr **AssocExprs,
+                       unsigned NumAssocs, SourceLocation DefaultLoc,
+                       SourceLocation RParenLoc,
+                       bool ContainsUnexpandedParameterPack);
+
+  explicit GenericSelectionExpr(EmptyShell Empty)
+    : Expr(GenericSelectionExprClass, Empty) { }
+
+  unsigned getNumAssocs() const { return NumAssocs; }
+
+  SourceLocation getGenericLoc() const { return GenericLoc; }
+  SourceLocation getDefaultLoc() const { return DefaultLoc; }
+  SourceLocation getRParenLoc() const { return RParenLoc; }
+
+  const Expr *getAssocExpr(unsigned i) const {
+    return cast<Expr>(SubExprs[END_EXPR+i]);
+  }
+  Expr *getAssocExpr(unsigned i) { return cast<Expr>(SubExprs[END_EXPR+i]); }
+
+  const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const {
+    return AssocTypes[i];
+  }
+  TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) { return AssocTypes[i]; }
+
+  QualType getAssocType(unsigned i) const {
+    if (const TypeSourceInfo *TS = getAssocTypeSourceInfo(i))
+      return TS->getType();
+    else
+      return QualType();
+  }
+
+  const Expr *getControllingExpr() const {
+    return cast<Expr>(SubExprs[CONTROLLING]);
+  }
+  Expr *getControllingExpr() { return cast<Expr>(SubExprs[CONTROLLING]); }
+
+  /// Whether this generic selection is result-dependent.
+  bool isResultDependent() const { return ResultIndex == -1U; }
+
+  /// The zero-based index of the result expression's generic association in
+  /// the generic selection's association list.  Defined only if the
+  /// generic selection is not result-dependent.
+  unsigned getResultIndex() const {
+    assert(!isResultDependent() && "Generic selection is result-dependent");
+    return ResultIndex;
+  }
+
+  /// The generic selection's result expression.  Defined only if the
+  /// generic selection is not result-dependent.
+  const Expr *getResultExpr() const { return getAssocExpr(getResultIndex()); }
+  Expr *getResultExpr() { return getAssocExpr(getResultIndex()); }
+
+  SourceRange getSourceRange() const {
+    return SourceRange(GenericLoc, RParenLoc);
+  }
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == GenericSelectionExprClass;
+  }
+  static bool classof(const GenericSelectionExpr *) { return true; }
+
+  child_range children() {
+    return child_range(SubExprs, SubExprs+END_EXPR+NumAssocs);
+  }
+
+  friend class ASTStmtReader;
+};
+
 //===----------------------------------------------------------------------===//
 // Clang Extensions
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Thu Apr 14 19:35:48 2011
@@ -1777,6 +1777,22 @@
   return true;
 }
 
+// GenericSelectionExpr is a special case because the types and expressions
+// are interleaved.  We also need to watch out for null types (default
+// generic associations).
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::
+TraverseGenericSelectionExpr(GenericSelectionExpr *S) {
+  TRY_TO(WalkUpFromGenericSelectionExpr(S));
+  TRY_TO(TraverseStmt(S->getControllingExpr()));
+  for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
+    if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i))
+      TRY_TO(TraverseTypeLoc(TS->getTypeLoc()));
+    TRY_TO(TraverseStmt(S->getAssocExpr(i)));
+  }
+  return true;
+}
+
 DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, {
     // This is called for code like 'return T()' where T is a built-in
     // (i.e. non-class) type.

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Thu Apr 14 19:35:48 2011
@@ -67,6 +67,13 @@
   "enumeration types with a fixed underlying type are a Microsoft extension">, 
   InGroup<Microsoft>;
 
+def ext_c1x_generic_selection : Extension<
+  "generic selections are a C1X-specific feature">;
+def err_duplicate_default_assoc : Error<
+  "duplicate default generic association">;
+def note_previous_default_assoc : Note<
+  "previous default generic association is here">;
+
 def ext_gnu_indirect_goto : Extension<
   "use of GNU indirect-goto extension">, InGroup<GNU>;
 def ext_gnu_address_of_label : Extension<

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Apr 14 19:35:48 2011
@@ -3646,6 +3646,21 @@
   "result of comparison against %select{a string literal|@encode}0 is "
   "unspecified (use strncmp instead)">;
 
+// Generic selections.
+def err_assoc_type_incomplete : Error<
+  "type %0 in generic association incomplete">;
+def err_assoc_type_nonobject : Error<
+  "type %0 in generic association not an object type">;
+def err_assoc_type_variably_modified : Error<
+  "type %0 in generic association is a variably modified type">;
+def err_assoc_compatible_types : Error<
+  "type %0 in generic association compatible with previously specified type %1">;
+def note_compat_assoc : Note<
+  "compatible type %0 specified here">;
+def err_generic_sel_no_match : Error<
+  "controlling expression type %0 not compatible with any generic association type">;
+def err_generic_sel_multi_match : Error<
+  "controlling expression type %0 compatible with %1 generic association types">;
 
 
 // Blocks

Modified: cfe/trunk/include/clang/Basic/StmtNodes.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/StmtNodes.td (original)
+++ cfe/trunk/include/clang/Basic/StmtNodes.td Thu Apr 14 19:35:48 2011
@@ -75,6 +75,7 @@
 def ImplicitValueInitExpr : DStmt<Expr>;
 def ParenListExpr : DStmt<Expr>;
 def VAArgExpr : DStmt<Expr>;
+def GenericSelectionExpr : DStmt<Expr>;
 
 // GNU Extensions.
 def AddrLabelExpr : DStmt<Expr>;

Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Thu Apr 14 19:35:48 2011
@@ -238,6 +238,7 @@
 KEYWORD(while                       , KEYALL)
 KEYWORD(_Bool                       , KEYNOCXX)
 KEYWORD(_Complex                    , KEYALL)
+KEYWORD(_Generic                    , KEYALL)
 KEYWORD(_Imaginary                  , KEYALL)
 KEYWORD(__func__                    , KEYALL)
 

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Thu Apr 14 19:35:48 2011
@@ -1101,6 +1101,8 @@
 
   ExprResult ParseStringLiteralExpression();
 
+  ExprResult ParseGenericSelectionExpression();
+
   //===--------------------------------------------------------------------===//
   // C++ Expressions
   ExprResult ParseCXXIdExpression(bool isAddressOfOperand = false);

Modified: cfe/trunk/include/clang/Sema/Ownership.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Ownership.h?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Ownership.h (original)
+++ cfe/trunk/include/clang/Sema/Ownership.h Thu Apr 14 19:35:48 2011
@@ -383,11 +383,18 @@
     template<typename T> T **takeAs() { return reinterpret_cast<T**>(take()); }
   };
 
+  /// An opaque type for threading parsed type information through the
+  /// parser.
+  typedef OpaquePtr<QualType> ParsedType;
+  typedef UnionOpaquePtr<QualType> UnionParsedType;
+
   /// A SmallVector of statements, with stack size 32 (as that is the only one
   /// used.)
   typedef ASTOwningVector<Stmt*, 32> StmtVector;
   /// A SmallVector of expressions, with stack size 12 (the maximum used.)
   typedef ASTOwningVector<Expr*, 12> ExprVector;
+  /// A SmallVector of types.
+  typedef ASTOwningVector<ParsedType, 12> TypeVector;
 
   template <class T, unsigned N> inline
   ASTMultiPtr<T> move_arg(ASTOwningVector<T, N> &vec) {
@@ -421,11 +428,6 @@
     static const bool value = true;
   };
 
-  /// An opaque type for threading parsed type information through the
-  /// parser.
-  typedef OpaquePtr<QualType> ParsedType;
-  typedef UnionOpaquePtr<QualType> UnionParsedType;
-
   typedef ActionResult<Expr*> ExprResult;
   typedef ActionResult<Stmt*> StmtResult;
   typedef ActionResult<ParsedType> TypeResult;
@@ -440,6 +442,7 @@
 
   typedef ASTMultiPtr<Expr*> MultiExprArg;
   typedef ASTMultiPtr<Stmt*> MultiStmtArg;
+  typedef ASTMultiPtr<ParsedType> MultiTypeArg;
   typedef ASTMultiPtr<TemplateParameterList*> MultiTemplateParamsArg;
 
   inline ExprResult ExprError() { return ExprResult(true); }

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Apr 14 19:35:48 2011
@@ -2009,6 +2009,20 @@
   /// fragments (e.g. "foo" "bar" L"baz").
   ExprResult ActOnStringLiteral(const Token *Toks, unsigned NumToks);
 
+  ExprResult ActOnGenericSelectionExpr(SourceLocation KeyLoc,
+                                       SourceLocation DefaultLoc,
+                                       SourceLocation RParenLoc,
+                                       Expr *ControllingExpr,
+                                       MultiTypeArg Types,
+                                       MultiExprArg Exprs);
+  ExprResult CreateGenericSelectionExpr(SourceLocation KeyLoc,
+                                        SourceLocation DefaultLoc,
+                                        SourceLocation RParenLoc,
+                                        Expr *ControllingExpr,
+                                        TypeSourceInfo **Types,
+                                        Expr **Exprs,
+                                        unsigned NumAssocs);
+
   // Binary/Unary Operators.  'Tok' is the token for the operator.
   ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
                                   Expr *InputArg);

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Thu Apr 14 19:35:48 2011
@@ -878,6 +878,8 @@
       EXPR_BLOCK,
       /// \brief A BlockDeclRef record.
       EXPR_BLOCK_DECL_REF,
+      /// \brief A GenericSelectionExpr record.
+      EXPR_GENERIC_SELECTION,
       
       // Objective-C
 

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Thu Apr 14 19:35:48 2011
@@ -35,18 +35,16 @@
 /// but also int expressions which are produced by things like comparisons in
 /// C.
 bool Expr::isKnownToHaveBooleanValue() const {
+  const Expr *E = IgnoreParens();
+
   // If this value has _Bool type, it is obvious 0/1.
-  if (getType()->isBooleanType()) return true;
+  if (E->getType()->isBooleanType()) return true;
   // If this is a non-scalar-integer type, we don't care enough to try. 
-  if (!getType()->isIntegralOrEnumerationType()) return false;
-  
-  if (const ParenExpr *PE = dyn_cast<ParenExpr>(this))
-    return PE->getSubExpr()->isKnownToHaveBooleanValue();
+  if (!E->getType()->isIntegralOrEnumerationType()) return false;
   
-  if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(this)) {
+  if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
     switch (UO->getOpcode()) {
     case UO_Plus:
-    case UO_Extension:
       return UO->getSubExpr()->isKnownToHaveBooleanValue();
     default:
       return false;
@@ -55,10 +53,10 @@
   
   // Only look through implicit casts.  If the user writes
   // '(int) (a && b)' treat it as an arbitrary int.
-  if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(this))
+  if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E))
     return CE->getSubExpr()->isKnownToHaveBooleanValue();
   
-  if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(this)) {
+  if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
     switch (BO->getOpcode()) {
     default: return false;
     case BO_LT:   // Relational operators.
@@ -84,7 +82,7 @@
     }
   }
   
-  if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(this))
+  if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E))
     return CO->getTrueExpr()->isKnownToHaveBooleanValue() &&
            CO->getFalseExpr()->isKnownToHaveBooleanValue();
   
@@ -1363,6 +1361,9 @@
   case ParenExprClass:
     return cast<ParenExpr>(this)->getSubExpr()->
       isUnusedResultAWarning(Loc, R1, R2, Ctx);
+  case GenericSelectionExprClass:
+    return cast<GenericSelectionExpr>(this)->getResultExpr()->
+      isUnusedResultAWarning(Loc, R1, R2, Ctx);
   case UnaryOperatorClass: {
     const UnaryOperator *UO = cast<UnaryOperator>(this);
 
@@ -1573,21 +1574,20 @@
 /// isOBJCGCCandidate - Check if an expression is objc gc'able.
 /// returns true, if it is; false otherwise.
 bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {
-  switch (getStmtClass()) {
+  const Expr *E = IgnoreParens();
+  switch (E->getStmtClass()) {
   default:
     return false;
   case ObjCIvarRefExprClass:
     return true;
   case Expr::UnaryOperatorClass:
-    return cast<UnaryOperator>(this)->getSubExpr()->isOBJCGCCandidate(Ctx);
-  case ParenExprClass:
-    return cast<ParenExpr>(this)->getSubExpr()->isOBJCGCCandidate(Ctx);
+    return cast<UnaryOperator>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
   case ImplicitCastExprClass:
-    return cast<ImplicitCastExpr>(this)->getSubExpr()->isOBJCGCCandidate(Ctx);
+    return cast<ImplicitCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
   case CStyleCastExprClass:
-    return cast<CStyleCastExpr>(this)->getSubExpr()->isOBJCGCCandidate(Ctx);
+    return cast<CStyleCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
   case DeclRefExprClass: {
-    const Decl *D = cast<DeclRefExpr>(this)->getDecl();
+    const Decl *D = cast<DeclRefExpr>(E)->getDecl();
     if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
       if (VD->hasGlobalStorage())
         return true;
@@ -1600,11 +1600,11 @@
     return false;
   }
   case MemberExprClass: {
-    const MemberExpr *M = cast<MemberExpr>(this);
+    const MemberExpr *M = cast<MemberExpr>(E);
     return M->getBase()->isOBJCGCCandidate(Ctx);
   }
   case ArraySubscriptExprClass:
-    return cast<ArraySubscriptExpr>(this)->getBase()->isOBJCGCCandidate(Ctx);
+    return cast<ArraySubscriptExpr>(E)->getBase()->isOBJCGCCandidate(Ctx);
   }
 }
 
@@ -1827,6 +1827,11 @@
       return CT_Dependent;
     return cast<ChooseExpr>(this)->getChosenSubExpr(C)->CanThrow(C);
 
+  case GenericSelectionExprClass:
+    if (cast<GenericSelectionExpr>(this)->isResultDependent())
+      return CT_Dependent;
+    return cast<GenericSelectionExpr>(this)->getResultExpr()->CanThrow(C);
+
     // Some expressions are always dependent.
   case DependentScopeDeclRefExprClass:
   case CXXUnresolvedConstructExprClass:
@@ -1853,6 +1858,12 @@
         continue;
       }
     }
+    if (GenericSelectionExpr* P = dyn_cast<GenericSelectionExpr>(E)) {
+      if (!P->isResultDependent()) {
+        E = P->getResultExpr();
+        continue;
+      }
+    }
     return E;
   }
 }
@@ -1876,6 +1887,12 @@
         continue;
       }
     }
+    if (GenericSelectionExpr* P = dyn_cast<GenericSelectionExpr>(E)) {
+      if (!P->isResultDependent()) {
+        E = P->getResultExpr();
+        continue;
+      }
+    }
     return E;
   }
 }
@@ -1900,6 +1917,11 @@
         E = P->getSubExpr();
         continue;
       }
+    } else if (GenericSelectionExpr* P = dyn_cast<GenericSelectionExpr>(E)) {
+      if (!P->isResultDependent()) {
+        E = P->getResultExpr();
+        continue;
+      }
     }
     break;
   }
@@ -1923,6 +1945,12 @@
         continue;
       }
     }
+    if (GenericSelectionExpr* P = dyn_cast<GenericSelectionExpr>(E)) {
+      if (!P->isResultDependent()) {
+        E = P->getResultExpr();
+        continue;
+      }
+    }
     return E;
   }
 }
@@ -1965,6 +1993,13 @@
       }
     }
 
+    if (GenericSelectionExpr* P = dyn_cast<GenericSelectionExpr>(E)) {
+      if (!P->isResultDependent()) {
+        E = P->getResultExpr();
+        continue;
+      }
+    }
+
     return E;
   }
 }
@@ -2156,6 +2191,11 @@
   case ParenExprClass:
     return cast<ParenExpr>(this)->getSubExpr()
       ->isConstantInitializer(Ctx, IsForRef);
+  case GenericSelectionExprClass:
+    if (cast<GenericSelectionExpr>(this)->isResultDependent())
+      return false;
+    return cast<GenericSelectionExpr>(this)->getResultExpr()
+      ->isConstantInitializer(Ctx, IsForRef);
   case ChooseExprClass:
     return cast<ChooseExpr>(this)->getChosenSubExpr(Ctx)
       ->isConstantInitializer(Ctx, IsForRef);
@@ -2242,6 +2282,9 @@
     // Accept ((void*)0) as a null pointer constant, as many other
     // implementations do.
     return PE->getSubExpr()->isNullPointerConstant(Ctx, NPC);
+  } else if (const GenericSelectionExpr *GE =
+               dyn_cast<GenericSelectionExpr>(this)) {
+    return GE->getResultExpr()->isNullPointerConstant(Ctx, NPC);
   } else if (const CXXDefaultArgExpr *DefaultArg
                = dyn_cast<CXXDefaultArgExpr>(this)) {
     // See through default argument expressions
@@ -2640,6 +2683,51 @@
   memcpy(SubExprs, Exprs, sizeof(Expr *) * NumExprs);
 }
 
+GenericSelectionExpr::GenericSelectionExpr(ASTContext &Context,
+                               SourceLocation GenericLoc, Expr *ControllingExpr,
+                               TypeSourceInfo **AssocTypes, Expr **AssocExprs,
+                               unsigned NumAssocs, SourceLocation DefaultLoc,
+                               SourceLocation RParenLoc,
+                               bool ContainsUnexpandedParameterPack,
+                               unsigned ResultIndex)
+  : Expr(GenericSelectionExprClass,
+         AssocExprs[ResultIndex]->getType(),
+         AssocExprs[ResultIndex]->getValueKind(),
+         AssocExprs[ResultIndex]->getObjectKind(),
+         AssocExprs[ResultIndex]->isTypeDependent(),
+         AssocExprs[ResultIndex]->isValueDependent(),
+         ContainsUnexpandedParameterPack),
+    AssocTypes(new (Context) TypeSourceInfo*[NumAssocs]),
+    SubExprs(new (Context) Stmt*[END_EXPR+NumAssocs]), NumAssocs(NumAssocs),
+    ResultIndex(ResultIndex), GenericLoc(GenericLoc), DefaultLoc(DefaultLoc),
+    RParenLoc(RParenLoc) {
+  SubExprs[CONTROLLING] = ControllingExpr;
+  std::copy(AssocTypes, AssocTypes+NumAssocs, this->AssocTypes);
+  std::copy(AssocExprs, AssocExprs+NumAssocs, SubExprs+END_EXPR);
+}
+
+GenericSelectionExpr::GenericSelectionExpr(ASTContext &Context,
+                               SourceLocation GenericLoc, Expr *ControllingExpr,
+                               TypeSourceInfo **AssocTypes, Expr **AssocExprs,
+                               unsigned NumAssocs, SourceLocation DefaultLoc,
+                               SourceLocation RParenLoc,
+                               bool ContainsUnexpandedParameterPack)
+  : Expr(GenericSelectionExprClass,
+         Context.DependentTy,
+         VK_RValue,
+         OK_Ordinary,
+         /*isTypeDependent=*/  true,
+         /*isValueDependent=*/ true,
+         ContainsUnexpandedParameterPack),
+    AssocTypes(new (Context) TypeSourceInfo*[NumAssocs]),
+    SubExprs(new (Context) Stmt*[END_EXPR+NumAssocs]), NumAssocs(NumAssocs),
+    ResultIndex(-1U), GenericLoc(GenericLoc), DefaultLoc(DefaultLoc),
+    RParenLoc(RParenLoc) {
+  SubExprs[CONTROLLING] = ControllingExpr;
+  std::copy(AssocTypes, AssocTypes+NumAssocs, this->AssocTypes);
+  std::copy(AssocExprs, AssocExprs+NumAssocs, SubExprs+END_EXPR);
+}
+
 //===----------------------------------------------------------------------===//
 //  DesignatedInitExpr
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/AST/ExprClassification.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprClassification.cpp (original)
+++ cfe/trunk/lib/AST/ExprClassification.cpp Thu Apr 14 19:35:48 2011
@@ -233,6 +233,14 @@
   case Expr::ParenExprClass:
     return ClassifyInternal(Ctx, cast<ParenExpr>(E)->getSubExpr());
 
+    // C1X 6.5.1.1p4: [A generic selection] is an lvalue, a function designator,
+    // or a void expression if its result expression is, respectively, an
+    // lvalue, a function designator, or a void expression.
+  case Expr::GenericSelectionExprClass:
+    if (cast<GenericSelectionExpr>(E)->isResultDependent())
+      return Cl::CL_PRValue;
+    return ClassifyInternal(Ctx,cast<GenericSelectionExpr>(E)->getResultExpr());
+
   case Expr::BinaryOperatorClass:
   case Expr::CompoundAssignOperatorClass:
     // C doesn't have any binary expressions that are lvalues.

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Apr 14 19:35:48 2011
@@ -274,6 +274,9 @@
   }
 
   bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
+  bool VisitGenericSelectionExpr(GenericSelectionExpr *E) {
+    return Visit(E->getResultExpr());
+  }
   bool VisitDeclRefExpr(DeclRefExpr *E) {
     if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified())
       return true;
@@ -372,6 +375,9 @@
   }
   
   bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
+  bool VisitGenericSelectionExpr(GenericSelectionExpr *E) {
+    return Visit(E->getResultExpr());
+  }
   bool VisitDeclRefExpr(DeclRefExpr *E);
   bool VisitPredefinedExpr(PredefinedExpr *E) { return Success(E); }
   bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
@@ -501,6 +507,9 @@
   }
 
   bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
+  bool VisitGenericSelectionExpr(GenericSelectionExpr *E) {
+    return Visit(E->getResultExpr());
+  }
 
   bool VisitBinaryOperator(const BinaryOperator *E);
   bool VisitCastExpr(CastExpr* E);
@@ -717,6 +726,8 @@
 
     APValue VisitParenExpr(ParenExpr *E)
         { return Visit(E->getSubExpr()); }
+    APValue VisitGenericSelectionExpr(GenericSelectionExpr *E)
+        { return Visit(E->getResultExpr()); }
     APValue VisitUnaryExtension(const UnaryOperator *E)
       { return Visit(E->getSubExpr()); }
     APValue VisitUnaryPlus(const UnaryOperator *E)
@@ -975,6 +986,9 @@
   }
 
   bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
+  bool VisitGenericSelectionExpr(GenericSelectionExpr *E) {
+    return Visit(E->getResultExpr());
+  }
 
   bool VisitIntegerLiteral(const IntegerLiteral *E) {
     return Success(E->getValue(), E);
@@ -1918,6 +1932,9 @@
   }
 
   bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
+  bool VisitGenericSelectionExpr(GenericSelectionExpr *E) {
+    return Visit(E->getResultExpr());
+  }
   bool VisitCallExpr(const CallExpr *E);
 
   bool VisitUnaryOperator(const UnaryOperator *E);
@@ -2251,6 +2268,9 @@
   }
 
   bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
+  bool VisitGenericSelectionExpr(GenericSelectionExpr *E) {
+    return Visit(E->getResultExpr());
+  }
 
   bool VisitImaginaryLiteral(ImaginaryLiteral *E);
 
@@ -2839,6 +2859,8 @@
 
   case Expr::ParenExprClass:
     return CheckICE(cast<ParenExpr>(E)->getSubExpr(), Ctx);
+  case Expr::GenericSelectionExprClass:
+    return CheckICE(cast<GenericSelectionExpr>(E)->getResultExpr(), Ctx);
   case Expr::IntegerLiteralClass:
   case Expr::CharacterLiteralClass:
   case Expr::CXXBoolLiteralExprClass:

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Thu Apr 14 19:35:48 2011
@@ -1750,6 +1750,7 @@
   case Expr::ChooseExprClass:
   case Expr::CompoundLiteralExprClass:
   case Expr::ExtVectorElementExprClass:
+  case Expr::GenericSelectionExprClass:
   case Expr::ObjCEncodeExprClass:
   case Expr::ObjCIsaExprClass:
   case Expr::ObjCIvarRefExprClass:

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Thu Apr 14 19:35:48 2011
@@ -737,6 +737,23 @@
     PrintExpr(Node->getArgumentExpr());
   }
 }
+
+void StmtPrinter::VisitGenericSelectionExpr(GenericSelectionExpr *Node) {
+  OS << "_Generic(";
+  PrintExpr(Node->getControllingExpr());
+  for (unsigned i = 0; i != Node->getNumAssocs(); ++i) {
+    OS << ", ";
+    QualType T = Node->getAssocType(i);
+    if (T.isNull())
+      OS << "default";
+    else
+      OS << T.getAsString(Policy);
+    OS << ": ";
+    PrintExpr(Node->getAssocExpr(i));
+  }
+  OS << ")";
+}
+
 void StmtPrinter::VisitArraySubscriptExpr(ArraySubscriptExpr *Node) {
   PrintExpr(Node->getLHS());
   OS << "[";

Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Thu Apr 14 19:35:48 2011
@@ -434,6 +434,18 @@
   ID.AddBoolean(S->isConstQualAdded());
 }
 
+void StmtProfiler::VisitGenericSelectionExpr(GenericSelectionExpr *S) {
+  VisitExpr(S);
+  for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
+    QualType T = S->getAssocType(i);
+    if (T.isNull())
+      ID.AddPointer(0);
+    else
+      VisitType(T);
+    VisitExpr(S->getAssocExpr(i));
+  }
+}
+
 static Stmt::StmtClass DecodeOperatorCall(CXXOperatorCallExpr *S,
                                           UnaryOperatorKind &UnaryOp,
                                           BinaryOperatorKind &BinaryOp) {

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Apr 14 19:35:48 2011
@@ -239,10 +239,7 @@
 
     llvm::SmallVector<SubobjectAdjustment, 2> Adjustments;
     while (true) {
-      if (const ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
-        E = PE->getSubExpr();
-        continue;
-      } 
+      E = E->IgnoreParens();
 
       if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
         if ((CE->getCastKind() == CK_DerivedToBase ||
@@ -545,6 +542,8 @@
   case Expr::DeclRefExprClass:
     return EmitDeclRefLValue(cast<DeclRefExpr>(E));
   case Expr::ParenExprClass:return EmitLValue(cast<ParenExpr>(E)->getSubExpr());
+  case Expr::GenericSelectionExprClass:
+    return EmitLValue(cast<GenericSelectionExpr>(E)->getResultExpr());
   case Expr::PredefinedExprClass:
     return EmitPredefinedLValue(cast<PredefinedExpr>(E));
   case Expr::StringLiteralClass:
@@ -1099,6 +1098,12 @@
     }
     return;
   }
+
+  if (const GenericSelectionExpr *Exp = dyn_cast<GenericSelectionExpr>(E)) {
+    setObjCGCLValueClass(Ctx, Exp->getResultExpr(), LV);
+    return;
+  }
+
   if (const ImplicitCastExpr *Exp = dyn_cast<ImplicitCastExpr>(E)) {
     setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
     return;

Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Thu Apr 14 19:35:48 2011
@@ -81,6 +81,9 @@
     CGF.ErrorUnsupported(S, "aggregate expression");
   }
   void VisitParenExpr(ParenExpr *PE) { Visit(PE->getSubExpr()); }
+  void VisitGenericSelectionExpr(GenericSelectionExpr *GE) {
+    Visit(GE->getResultExpr());
+  }
   void VisitUnaryExtension(UnaryOperator *E) { Visit(E->getSubExpr()); }
 
   // l-values.
@@ -518,9 +521,8 @@
 /// zero to memory, return true.  This can return false if uncertain, so it just
 /// handles simple cases.
 static bool isSimpleZero(const Expr *E, CodeGenFunction &CGF) {
-  // (0)
-  if (const ParenExpr *PE = dyn_cast<ParenExpr>(E))
-    return isSimpleZero(PE->getSubExpr(), CGF);
+  E = E->IgnoreParens();
+
   // 0
   if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(E))
     return IL->getValue() == 0;
@@ -743,8 +745,7 @@
 /// non-zero bytes that will be stored when outputting the initializer for the
 /// specified initializer expression.
 static uint64_t GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) {
-  if (const ParenExpr *PE = dyn_cast<ParenExpr>(E))
-    return GetNumNonZeroBytesInInit(PE->getSubExpr(), CGF);
+  E = E->IgnoreParens();
 
   // 0 and 0.0 won't require any non-zero stores!
   if (isSimpleZero(E, CGF)) return 0;

Modified: cfe/trunk/lib/CodeGen/CGExprComplex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprComplex.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprComplex.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprComplex.cpp Thu Apr 14 19:35:48 2011
@@ -108,6 +108,9 @@
   }
   ComplexPairTy VisitExpr(Expr *S);
   ComplexPairTy VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr());}
+  ComplexPairTy VisitGenericSelectionExpr(GenericSelectionExpr *GE) {
+    return Visit(GE->getResultExpr());
+  }
   ComplexPairTy VisitImaginaryLiteral(const ImaginaryLiteral *IL);
 
   // l-values.

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Thu Apr 14 19:35:48 2011
@@ -457,6 +457,10 @@
     return Visit(PE->getSubExpr());
   }
 
+  llvm::Constant *VisitGenericSelectionExpr(GenericSelectionExpr *GE) {
+    return Visit(GE->getResultExpr());
+  }
+
   llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
     return Visit(E->getInitializer());
   }

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Thu Apr 14 19:35:48 2011
@@ -163,6 +163,9 @@
   Value *VisitParenExpr(ParenExpr *PE) {
     return Visit(PE->getSubExpr()); 
   }
+  Value *VisitGenericSelectionExpr(GenericSelectionExpr *GE) {
+    return Visit(GE->getResultExpr());
+  }
 
   // Leaves.
   Value *VisitIntegerLiteral(const IntegerLiteral *E) {
@@ -2396,8 +2399,7 @@
 /// flow into selects in some cases.
 static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E,
                                                    CodeGenFunction &CGF) {
-  if (const ParenExpr *PE = dyn_cast<ParenExpr>(E))
-    return isCheapEnoughToEvaluateUnconditionally(PE->getSubExpr(), CGF);
+  E = E->IgnoreParens();
 
   // TODO: Allow anything we can constant fold to an integer or fp constant.
   if (isa<IntegerLiteral>(E) || isa<CharacterLiteral>(E) ||

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Thu Apr 14 19:35:48 2011
@@ -469,8 +469,7 @@
 void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
                                            llvm::BasicBlock *TrueBlock,
                                            llvm::BasicBlock *FalseBlock) {
-  if (const ParenExpr *PE = dyn_cast<ParenExpr>(Cond))
-    return EmitBranchOnBoolExpr(PE->getSubExpr(), TrueBlock, FalseBlock);
+  Cond = Cond->IgnoreParens();
 
   if (const BinaryOperator *CondBOp = dyn_cast<BinaryOperator>(Cond)) {
     // Handle X && Y in a condition.

Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)
+++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Thu Apr 14 19:35:48 2011
@@ -548,6 +548,7 @@
            .Case("cxx_exceptions", LangOpts.Exceptions)
            .Case("cxx_rtti", LangOpts.RTTI)
            .Case("enumerator_attributes", true)
+           .Case("generic_selections", true)
            .Case("objc_nonfragile_abi", LangOpts.ObjCNonFragileABI)
            .Case("objc_weak_class", LangOpts.ObjCNonFragileABI)
            .Case("ownership_holds", true)

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Thu Apr 14 19:35:48 2011
@@ -465,6 +465,7 @@
 /// [C++]   boolean-literal  [C++ 2.13.5]
 /// [C++0x] 'nullptr'        [C++0x 2.14.7]
 ///         '(' expression ')'
+/// [C1X]   generic-selection
 ///         '__func__'        [C99 6.4.2.2]
 /// [GNU]   '__FUNCTION__'
 /// [GNU]   '__PRETTY_FUNCTION__'
@@ -731,6 +732,9 @@
   case tok::wide_string_literal:
     Res = ParseStringLiteralExpression();
     break;
+  case tok::kw__Generic:   // primary-expression: generic-selection [C1X 6.5.1]
+    Res = ParseGenericSelectionExpression();
+    break;
   case tok::kw___builtin_va_arg:
   case tok::kw___builtin_offsetof:
   case tok::kw___builtin_choose_expr:
@@ -1802,6 +1806,100 @@
   return Actions.ActOnStringLiteral(&StringToks[0], StringToks.size());
 }
 
+/// ParseGenericSelectionExpression - Parse a C1X generic-selection
+/// [C1X 6.5.1.1].
+///
+///    generic-selection:
+///           _Generic ( assignment-expression , generic-assoc-list )
+///    generic-assoc-list:
+///           generic-association
+///           generic-assoc-list , generic-association
+///    generic-association:
+///           type-name : assignment-expression
+///           default : assignment-expression
+ExprResult Parser::ParseGenericSelectionExpression() {
+  assert(Tok.is(tok::kw__Generic) && "_Generic keyword expected");
+  SourceLocation KeyLoc = ConsumeToken();
+
+  if (!getLang().C1X)
+    Diag(KeyLoc, diag::ext_c1x_generic_selection);
+
+  SourceLocation LParenLoc = Tok.getLocation();
+  if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen, ""))
+    return ExprError();
+
+  ExprResult ControllingExpr;
+  {
+    // C1X 6.5.1.1p3 "The controlling expression of a generic selection is
+    // not evaluated."
+    EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
+    ControllingExpr = ParseAssignmentExpression();
+    if (ControllingExpr.isInvalid()) {
+      SkipUntil(tok::r_paren);
+      return ExprError();
+    }
+  }
+
+  if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "")) {
+    SkipUntil(tok::r_paren);
+    return ExprError();
+  }
+
+  SourceLocation DefaultLoc;
+  TypeVector Types(Actions);
+  ExprVector Exprs(Actions);
+  while (1) {
+    ParsedType Ty;
+    if (Tok.is(tok::kw_default)) {
+      // C1X 6.5.1.1p2 "A generic selection shall have no more than one default
+      // generic association."
+      if (!DefaultLoc.isInvalid()) {
+        Diag(Tok, diag::err_duplicate_default_assoc);
+        Diag(DefaultLoc, diag::note_previous_default_assoc);
+        SkipUntil(tok::r_paren);
+        return ExprError();
+      }
+      DefaultLoc = ConsumeToken();
+      Ty = ParsedType();
+    } else {
+      ColonProtectionRAIIObject X(*this);
+      TypeResult TR = ParseTypeName();
+      if (TR.isInvalid()) {
+        SkipUntil(tok::r_paren);
+        return ExprError();
+      }
+      Ty = TR.release();
+    }
+    Types.push_back(Ty);
+
+    if (ExpectAndConsume(tok::colon, diag::err_expected_colon, "")) {
+      SkipUntil(tok::r_paren);
+      return ExprError();
+    }
+
+    // FIXME: These expressions should be parsed in a potentially potentially
+    // evaluated context.
+    ExprResult ER(ParseAssignmentExpression());
+    if (ER.isInvalid()) {
+      SkipUntil(tok::r_paren);
+      return ExprError();
+    }
+    Exprs.push_back(ER.release());
+
+    if (Tok.isNot(tok::comma))
+      break;
+    ConsumeToken();
+  }
+
+  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+  if (RParenLoc.isInvalid())
+    return ExprError();
+
+  return Actions.ActOnGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc,
+                                           ControllingExpr.release(),
+                                           move_arg(Types), move_arg(Exprs));
+}
+
 /// ParseExpressionList - Used for C/C++ (argument-)expression-list.
 ///
 ///       argument-expression-list:

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Thu Apr 14 19:35:48 2011
@@ -905,6 +905,8 @@
   if (E->isTypeDependent() || E->isValueDependent())
     return false;
 
+  E = E->IgnoreParens();
+
   switch (E->getStmtClass()) {
   case Stmt::BinaryConditionalOperatorClass:
   case Stmt::ConditionalOperatorClass: {
@@ -927,11 +929,6 @@
     goto tryAgain;
   }
 
-  case Stmt::ParenExprClass: {
-    E = cast<ParenExpr>(E)->getSubExpr();
-    goto tryAgain;
-  }
-
   case Stmt::OpaqueValueExprClass:
     if (const Expr *src = cast<OpaqueValueExpr>(E)->getSourceExpr()) {
       E = src;
@@ -1897,14 +1894,12 @@
           E->getType()->isObjCQualifiedIdType()) &&
          "EvalAddr only works on pointers");
 
+  E = E->IgnoreParens();
+
   // Our "symbolic interpreter" is just a dispatch off the currently
   // viewed AST node.  We then recursively traverse the AST by calling
   // EvalAddr and EvalVal appropriately.
   switch (E->getStmtClass()) {
-  case Stmt::ParenExprClass:
-    // Ignore parentheses.
-    return EvalAddr(cast<ParenExpr>(E)->getSubExpr(), refVars);
-
   case Stmt::DeclRefExprClass: {
     DeclRefExpr *DR = cast<DeclRefExpr>(E);
 
@@ -2034,6 +2029,8 @@
   // Our "symbolic interpreter" is just a dispatch off the currently
   // viewed AST node.  We then recursively traverse the AST by calling
   // EvalAddr and EvalVal appropriately.
+
+  E = E->IgnoreParens();
   switch (E->getStmtClass()) {
   case Stmt::ImplicitCastExprClass: {
     ImplicitCastExpr *IE = cast<ImplicitCastExpr>(E);
@@ -2067,12 +2064,6 @@
     return NULL;
   }
 
-  case Stmt::ParenExprClass: {
-    // Ignore parentheses.
-    E = cast<ParenExpr>(E)->getSubExpr();
-    continue;
-  }
-
   case Stmt::UnaryOperatorClass: {
     // The only unary operator that make sense to handle here
     // is Deref.  All others don't resolve to a "name."  This includes
@@ -3272,11 +3263,9 @@
 }
 
 void Sema::CheckArrayAccess(const Expr *expr) {
-  while (true)
+  while (true) {
+    expr = expr->IgnoreParens();
     switch (expr->getStmtClass()) {
-      case Stmt::ParenExprClass:
-        expr = cast<ParenExpr>(expr)->getSubExpr();
-        continue;
       case Stmt::ArraySubscriptExprClass:
         CheckArrayAccess_Check(*this, cast<ArraySubscriptExpr>(expr));
         return;
@@ -3291,4 +3280,5 @@
       default:
         return;
     }
+  }
 }

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Apr 14 19:35:48 2011
@@ -748,6 +748,163 @@
 //===----------------------------------------------------------------------===//
 
 
+ExprResult
+Sema::ActOnGenericSelectionExpr(SourceLocation KeyLoc,
+                                SourceLocation DefaultLoc,
+                                SourceLocation RParenLoc,
+                                Expr *ControllingExpr,
+                                MultiTypeArg types,
+                                MultiExprArg exprs) {
+  unsigned NumAssocs = types.size();
+  assert(NumAssocs == exprs.size());
+
+  ParsedType *ParsedTypes = types.release();
+  Expr **Exprs = exprs.release();
+
+  TypeSourceInfo **Types = new TypeSourceInfo*[NumAssocs];
+  for (unsigned i = 0; i < NumAssocs; ++i) {
+    if (ParsedTypes[i])
+      (void) GetTypeFromParser(ParsedTypes[i], &Types[i]);
+    else
+      Types[i] = 0;
+  }
+
+  ExprResult ER = CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc,
+                                             ControllingExpr, Types, Exprs,
+                                             NumAssocs);
+  delete Types;
+  return ER;
+}
+
+ExprResult
+Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
+                                 SourceLocation DefaultLoc,
+                                 SourceLocation RParenLoc,
+                                 Expr *ControllingExpr,
+                                 TypeSourceInfo **Types,
+                                 Expr **Exprs,
+                                 unsigned NumAssocs) {
+  bool TypeErrorFound = false,
+       IsResultDependent = ControllingExpr->isTypeDependent(),
+       ContainsUnexpandedParameterPack
+         = ControllingExpr->containsUnexpandedParameterPack();
+
+  for (unsigned i = 0; i < NumAssocs; ++i) {
+    if (Exprs[i]->containsUnexpandedParameterPack())
+      ContainsUnexpandedParameterPack = true;
+
+    if (Types[i]) {
+      if (Types[i]->getType()->containsUnexpandedParameterPack())
+        ContainsUnexpandedParameterPack = true;
+
+      if (Types[i]->getType()->isDependentType()) {
+        IsResultDependent = true;
+      } else {
+        // C1X 6.5.1.1p2 "The type name in a generic association shall specify a
+        // complete object type other than a variably modified type."
+        unsigned D = 0;
+        if (Types[i]->getType()->isIncompleteType())
+          D = diag::err_assoc_type_incomplete;
+        else if (!Types[i]->getType()->isObjectType())
+          D = diag::err_assoc_type_nonobject;
+        else if (Types[i]->getType()->isVariablyModifiedType())
+          D = diag::err_assoc_type_variably_modified;
+
+        if (D != 0) {
+          Diag(Types[i]->getTypeLoc().getBeginLoc(), D)
+            << Types[i]->getTypeLoc().getSourceRange()
+            << Types[i]->getType();
+          TypeErrorFound = true;
+        }
+
+        // C1X 6.5.1.1p2 "No two generic associations in the same generic
+        // selection shall specify compatible types."
+        for (unsigned j = i+1; j < NumAssocs; ++j)
+          if (Types[j] && !Types[j]->getType()->isDependentType() &&
+              Context.typesAreCompatible(Types[i]->getType(),
+                                         Types[j]->getType())) {
+            Diag(Types[j]->getTypeLoc().getBeginLoc(),
+                 diag::err_assoc_compatible_types)
+              << Types[j]->getTypeLoc().getSourceRange()
+              << Types[j]->getType()
+              << Types[i]->getType();
+            Diag(Types[i]->getTypeLoc().getBeginLoc(),
+                 diag::note_compat_assoc)
+              << Types[i]->getTypeLoc().getSourceRange()
+              << Types[i]->getType();
+            TypeErrorFound = true;
+          }
+      }
+    }
+  }
+  if (TypeErrorFound)
+    return ExprError();
+
+  // If we determined that the generic selection is result-dependent, don't
+  // try to compute the result expression.
+  if (IsResultDependent)
+    return Owned(new (Context) GenericSelectionExpr(
+                   Context, KeyLoc, ControllingExpr,
+                   Types, Exprs, NumAssocs, DefaultLoc,
+                   RParenLoc, ContainsUnexpandedParameterPack));
+
+  llvm::SmallVector<unsigned, 1> CompatIndices;
+  unsigned DefaultIndex = -1U;
+  for (unsigned i = 0; i < NumAssocs; ++i) {
+    if (!Types[i])
+      DefaultIndex = i;
+    else if (Context.typesAreCompatible(ControllingExpr->getType(),
+                                        Types[i]->getType()))
+      CompatIndices.push_back(i);
+  }
+
+  // C1X 6.5.1.1p2 "The controlling expression of a generic selection shall have
+  // type compatible with at most one of the types named in its generic
+  // association list."
+  if (CompatIndices.size() > 1) {
+    // We strip parens here because the controlling expression is typically
+    // parenthesized in macro definitions.
+    ControllingExpr = ControllingExpr->IgnoreParens();
+    Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_multi_match)
+      << ControllingExpr->getSourceRange() << ControllingExpr->getType()
+      << (unsigned) CompatIndices.size();
+    for (llvm::SmallVector<unsigned, 1>::iterator I = CompatIndices.begin(),
+         E = CompatIndices.end(); I != E; ++I) {
+      Diag(Types[*I]->getTypeLoc().getBeginLoc(),
+           diag::note_compat_assoc)
+        << Types[*I]->getTypeLoc().getSourceRange()
+        << Types[*I]->getType();
+    }
+    return ExprError();
+  }
+
+  // C1X 6.5.1.1p2 "If a generic selection has no default generic association,
+  // its controlling expression shall have type compatible with exactly one of
+  // the types named in its generic association list."
+  if (DefaultIndex == -1U && CompatIndices.size() == 0) {
+    // We strip parens here because the controlling expression is typically
+    // parenthesized in macro definitions.
+    ControllingExpr = ControllingExpr->IgnoreParens();
+    Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_no_match)
+      << ControllingExpr->getSourceRange() << ControllingExpr->getType();
+    return ExprError();
+  }
+
+  // C1X 6.5.1.1p3 "If a generic selection has a generic association with a
+  // type name that is compatible with the type of the controlling expression,
+  // then the result expression of the generic selection is the expression
+  // in that generic association. Otherwise, the result expression of the
+  // generic selection is the expression in the default generic association."
+  unsigned ResultIndex =
+    CompatIndices.size() ? CompatIndices[0] : DefaultIndex;
+
+  return Owned(new (Context) GenericSelectionExpr(
+                 Context, KeyLoc, ControllingExpr,
+                 Types, Exprs, NumAssocs, DefaultLoc,
+                 RParenLoc, ContainsUnexpandedParameterPack,
+                 ResultIndex));
+}
+
 /// ActOnStringLiteral - The specified tokens were lexed as pasted string
 /// fragments (e.g. "foo" "bar" L"baz").  The result string has to handle string
 /// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Apr 14 19:35:48 2011
@@ -1602,6 +1602,22 @@
                                    RParenLoc);
   }
 
+  /// \brief Build a new generic selection expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildGenericSelectionExpr(SourceLocation KeyLoc,
+                                         SourceLocation DefaultLoc,
+                                         SourceLocation RParenLoc,
+                                         Expr *ControllingExpr,
+                                         TypeSourceInfo **Types,
+                                         Expr **Exprs,
+                                         unsigned NumAssocs) {
+    return getSema().CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc,
+                                                ControllingExpr, Types, Exprs,
+                                                NumAssocs);
+  }
+
   /// \brief Build a new overloaded operator call expression.
   ///
   /// By default, performs semantic analysis to build the new expression.
@@ -5525,6 +5541,42 @@
 
 template<typename Derived>
 ExprResult
+TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) {
+  ExprResult ControllingExpr =
+    getDerived().TransformExpr(E->getControllingExpr());
+  if (ControllingExpr.isInvalid())
+    return ExprError();
+
+  llvm::SmallVector<Expr *, 4> AssocExprs;
+  llvm::SmallVector<TypeSourceInfo *, 4> AssocTypes;
+  for (unsigned i = 0; i != E->getNumAssocs(); ++i) {
+    TypeSourceInfo *TS = E->getAssocTypeSourceInfo(i);
+    if (TS) {
+      TypeSourceInfo *AssocType = getDerived().TransformType(TS);
+      if (!AssocType)
+        return ExprError();
+      AssocTypes.push_back(AssocType);
+    } else {
+      AssocTypes.push_back(0);
+    }
+
+    ExprResult AssocExpr = getDerived().TransformExpr(E->getAssocExpr(i));
+    if (AssocExpr.isInvalid())
+      return ExprError();
+    AssocExprs.push_back(AssocExpr.release());
+  }
+
+  return getDerived().RebuildGenericSelectionExpr(E->getGenericLoc(),
+                                                  E->getDefaultLoc(),
+                                                  E->getRParenLoc(),
+                                                  ControllingExpr.release(),
+                                                  AssocTypes.data(),
+                                                  AssocExprs.data(),
+                                                  E->getNumAssocs());
+}
+
+template<typename Derived>
+ExprResult
 TreeTransform<Derived>::TransformParenExpr(ParenExpr *E) {
   ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
   if (SubExpr.isInvalid())

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Thu Apr 14 19:35:48 2011
@@ -122,6 +122,7 @@
     void VisitShuffleVectorExpr(ShuffleVectorExpr *E);
     void VisitBlockExpr(BlockExpr *E);
     void VisitBlockDeclRefExpr(BlockDeclRefExpr *E);
+    void VisitGenericSelectionExpr(GenericSelectionExpr *E);
     void VisitObjCStringLiteral(ObjCStringLiteral *E);
     void VisitObjCEncodeExpr(ObjCEncodeExpr *E);
     void VisitObjCSelectorExpr(ObjCSelectorExpr *E);
@@ -822,6 +823,25 @@
   E->setConstQualAdded(Record[Idx++]);
 }
 
+void ASTStmtReader::VisitGenericSelectionExpr(GenericSelectionExpr *E) {
+  VisitExpr(E);
+  E->NumAssocs = Record[Idx++];
+  E->AssocTypes = new (*Reader.getContext()) TypeSourceInfo*[E->NumAssocs];
+  E->SubExprs =
+   new(*Reader.getContext()) Stmt*[GenericSelectionExpr::END_EXPR+E->NumAssocs];
+
+  E->SubExprs[GenericSelectionExpr::CONTROLLING] = Reader.ReadSubExpr();
+  for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) {
+    E->AssocTypes[I] = GetTypeSourceInfo(Record, Idx);
+    E->SubExprs[GenericSelectionExpr::END_EXPR+I] = Reader.ReadSubExpr();
+  }
+  E->ResultIndex = Record[Idx++];
+
+  E->GenericLoc = ReadSourceLocation(Record, Idx);
+  E->DefaultLoc = ReadSourceLocation(Record, Idx);
+  E->RParenLoc = ReadSourceLocation(Record, Idx);
+}
+
 //===----------------------------------------------------------------------===//
 // Objective-C Expressions and Statements
 
@@ -1696,6 +1716,10 @@
       S = new (Context) BlockDeclRefExpr(Empty);
       break;
 
+    case EXPR_GENERIC_SELECTION:
+      S = new (Context) GenericSelectionExpr(Empty);
+      break;
+
     case EXPR_OBJC_STRING_LITERAL:
       S = new (Context) ObjCStringLiteral(Empty);
       break;

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Thu Apr 14 19:35:48 2011
@@ -659,6 +659,7 @@
   RECORD(EXPR_SHUFFLE_VECTOR);
   RECORD(EXPR_BLOCK);
   RECORD(EXPR_BLOCK_DECL_REF);
+  RECORD(EXPR_GENERIC_SELECTION);
   RECORD(EXPR_OBJC_STRING_LITERAL);
   RECORD(EXPR_OBJC_ENCODE);
   RECORD(EXPR_OBJC_SELECTOR_EXPR);

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Thu Apr 14 19:35:48 2011
@@ -93,6 +93,7 @@
     void VisitShuffleVectorExpr(ShuffleVectorExpr *E);
     void VisitBlockExpr(BlockExpr *E);
     void VisitBlockDeclRefExpr(BlockDeclRefExpr *E);
+    void VisitGenericSelectionExpr(GenericSelectionExpr *E);
 
     // Objective-C Expressions
     void VisitObjCStringLiteral(ObjCStringLiteral *E);
@@ -785,6 +786,23 @@
   Code = serialization::EXPR_BLOCK_DECL_REF;
 }
 
+void ASTStmtWriter::VisitGenericSelectionExpr(GenericSelectionExpr *E) {
+  VisitExpr(E);
+  Record.push_back(E->getNumAssocs());
+
+  Writer.AddStmt(E->getControllingExpr());
+  for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) {
+    Writer.AddTypeSourceInfo(E->getAssocTypeSourceInfo(I), Record);
+    Writer.AddStmt(E->getAssocExpr(I));
+  }
+  Record.push_back(E->isResultDependent() ? -1U : E->getResultIndex());
+
+  Writer.AddSourceLocation(E->getGenericLoc(), Record);
+  Writer.AddSourceLocation(E->getDefaultLoc(), Record);
+  Writer.AddSourceLocation(E->getRParenLoc(), Record);
+  Code = serialization::EXPR_GENERIC_SELECTION;
+}
+
 //===----------------------------------------------------------------------===//
 // Objective-C Expressions and Statements.
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Thu Apr 14 19:35:48 2011
@@ -859,7 +859,8 @@
           default:
             break;
           case Stmt::ParenExprClass:
-            S = cast<ParenExpr>(S)->IgnoreParens();
+          case Stmt::GenericSelectionExprClass:
+            S = cast<Expr>(S)->IgnoreParens();
             firstCharOnly = true;
             continue;
           case Stmt::BinaryConditionalOperatorClass:

Modified: cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp Thu Apr 14 19:35:48 2011
@@ -41,6 +41,10 @@
         // ParenExprs are no-ops.
         E = cast<ParenExpr>(E)->getSubExpr();
         continue;
+      case Stmt::GenericSelectionExprClass:
+        // GenericSelectionExprs are no-ops.
+        E = cast<GenericSelectionExpr>(E)->getResultExpr();
+        continue;
       case Stmt::CharacterLiteralClass: {
         const CharacterLiteral* C = cast<CharacterLiteral>(E);
         return svalBuilder.makeIntVal(C->getValue(), C->getType());

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Thu Apr 14 19:35:48 2011
@@ -458,6 +458,8 @@
 
     case Stmt::ParenExprClass:
       llvm_unreachable("ParenExprs already handled.");
+    case Stmt::GenericSelectionExprClass:
+      llvm_unreachable("GenericSelectionExprs already handled.");
     // Cases that should never be evaluated simply because they shouldn't
     // appear in the CFG.
     case Stmt::BreakStmtClass:

Modified: cfe/trunk/test/PCH/exprs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/exprs.c?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/test/PCH/exprs.c (original)
+++ cfe/trunk/test/PCH/exprs.c Thu Apr 14 19:35:48 2011
@@ -93,3 +93,6 @@
 
 // ShuffleVectorExpr
 shuffle_expr *vec_ptr = &vec2;
+
+// GenericSelectionExpr
+generic_selection_expr *double_ptr6 = &floating;

Modified: cfe/trunk/test/PCH/exprs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/exprs.h?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/test/PCH/exprs.h (original)
+++ cfe/trunk/test/PCH/exprs.h Thu Apr 14 19:35:48 2011
@@ -99,3 +99,7 @@
 
 // ShuffleVectorExpr
 typedef typeof(__builtin_shufflevector(vec2, vec2b, 2, 1)) shuffle_expr;
+
+// GenericSelectionExpr
+typedef typeof(_Generic(i, char*: 0, int: 0., default: hello))
+  generic_selection_expr;

Added: cfe/trunk/test/Parser/c1x-generic-selection.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/c1x-generic-selection.c?rev=129554&view=auto
==============================================================================
--- cfe/trunk/test/Parser/c1x-generic-selection.c (added)
+++ cfe/trunk/test/Parser/c1x-generic-selection.c Thu Apr 14 19:35:48 2011
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -std=c1x -fsyntax-only -verify %s
+
+void foo(void) {
+  _Generic; // expected-error {{expected '('}}
+  (void) _Generic(0); // expected-error {{expected ','}}
+  (void) _Generic(0, void); // expected-error {{expected ':'}}
+  (void) _Generic(0,
+      default: 0,  // expected-note {{previous default generic association is here}}
+      default: 0); // expected-error {{duplicate default generic association}}
+}

Added: cfe/trunk/test/Sema/generic-selection.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/generic-selection.c?rev=129554&view=auto
==============================================================================
--- cfe/trunk/test/Sema/generic-selection.c (added)
+++ cfe/trunk/test/Sema/generic-selection.c Thu Apr 14 19:35:48 2011
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -std=c1x -fsyntax-only -verify %s
+
+void foo(int n) {
+  (void) _Generic(0,
+      struct A: 0, // expected-error {{type 'struct A' in generic association incomplete}}
+      void(): 0,   // expected-error {{type 'void ()' in generic association not an object type}}
+      int[n]: 0);  // expected-error {{type 'int [n]' in generic association is a variably modified type}}
+
+  (void) _Generic(0,
+      void (*)():     0,  // expected-note {{compatible type 'void (*)()' specified here}}
+      void (*)(void): 0); // expected-error {{type 'void (*)(void)' in generic association compatible with previously specified type 'void (*)()'}}
+
+  (void) _Generic((void (*)()) 0, // expected-error {{controlling expression type 'void (*)()' compatible with 2 generic association types}}
+      void (*)(int):  0,  // expected-note {{compatible type 'void (*)(int)' specified here}}
+      void (*)(void): 0); // expected-note {{compatible type 'void (*)(void)' specified here}}
+
+  (void) _Generic(0, // expected-error {{controlling expression type 'int' not compatible with any generic association type}}
+      char: 0, short: 0, long: 0);
+
+  int a1[_Generic(0, int: 1, short: 2, float: 3, default: 4) == 1 ? 1 : -1];
+  int a2[_Generic(0, default: 1, short: 2, float: 3, int: 4) == 4 ? 1 : -1];
+  int a3[_Generic(0L, int: 1, short: 2, float: 3, default: 4) == 4 ? 1 : -1];
+  int a4[_Generic(0L, default: 1, short: 2, float: 3, int: 4) == 1 ? 1 : -1];
+  int a5[_Generic(0, int: 1, short: 2, float: 3) == 1 ? 1 : -1];
+  int a6[_Generic(0, short: 1, float: 2, int: 3) == 3 ? 1 : -1];
+}

Added: cfe/trunk/test/SemaCXX/generic-selection.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/generic-selection.cpp?rev=129554&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/generic-selection.cpp (added)
+++ cfe/trunk/test/SemaCXX/generic-selection.cpp Thu Apr 14 19:35:48 2011
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+template <typename T, typename U = void*>
+struct A {
+  enum {
+    id = _Generic(T(), // expected-error {{controlling expression type 'char' not compatible with any generic association type}}
+        int: 1, // expected-note {{compatible type 'int' specified here}}
+        float: 2,
+        U: 3) // expected-error {{type 'int' in generic association compatible with previously specified type 'int'}}
+  };
+};
+
+static_assert(A<int>::id == 1, "fail");
+static_assert(A<float>::id == 2, "fail");
+static_assert(A<double, double>::id == 3, "fail");
+
+A<char> a1; // expected-note {{in instantiation of template class 'A<char, void *>' requested here}}
+A<short, int> a2; // expected-note {{in instantiation of template class 'A<short, int>' requested here}}
+
+template <typename T, typename U>
+struct B {
+  enum {
+    id = _Generic(T(),
+        int: 1, // expected-note {{compatible type 'int' specified here}}
+        int: 2, // expected-error {{type 'int' in generic association compatible with previously specified type 'int'}}
+        U: 3)
+  };
+};
+
+template <unsigned Arg, unsigned... Args> struct Or {
+  enum { result = Arg | Or<Args...>::result };
+};
+
+template <unsigned Arg> struct Or<Arg> {
+  enum { result = Arg };
+};
+
+template <class... Args> struct TypeMask {
+  enum {
+   result = Or<_Generic(Args(), int: 1, long: 2, short: 4, float: 8)...>::result
+  };
+};
+
+static_assert(TypeMask<int, long, short>::result == 7, "fail");
+static_assert(TypeMask<float, short>::result == 12, "fail");
+static_assert(TypeMask<int, float, float>::result == 9, "fail");

Modified: cfe/trunk/tools/libclang/CXCursor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=129554&r1=129553&r2=129554&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.cpp (original)
+++ cfe/trunk/tools/libclang/CXCursor.cpp Thu Apr 14 19:35:48 2011
@@ -130,6 +130,7 @@
   case Stmt::AddrLabelExprClass:        
   case Stmt::StmtExprClass:             
   case Stmt::ChooseExprClass:           
+  case Stmt::GenericSelectionExprClass:
   case Stmt::GNUNullExprClass:          
   case Stmt::CXXStaticCastExprClass:      
   case Stmt::CXXDynamicCastExprClass:     





More information about the cfe-commits mailing list