[cfe-commits] r64336 - in /cfe/trunk: include/clang/AST/Attr.h include/clang/Basic/DiagnosticSemaKinds.def include/clang/Parse/AttributeList.h lib/Parse/AttributeList.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclAttr.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaLookup.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaOverload.h

Douglas Gregor dgregor at apple.com
Wed Feb 11 15:02:50 PST 2009


Author: dgregor
Date: Wed Feb 11 17:02:49 2009
New Revision: 64336

URL: http://llvm.org/viewvc/llvm-project?rev=64336&view=rev
Log:
Initial implementation of function overloading in C.

This commit adds a new attribute, "overloadable", that enables C++
function overloading in C. The attribute can only be added to function
declarations, e.g.,

  int *f(int) __attribute__((overloadable));

If the "overloadable" attribute exists on a function with a given
name, *all* functions with that name (and in that scope) must have the
"overloadable" attribute. Sets of overloaded functions with the
"overloadable" attribute then follow the normal C++ rules for
overloaded functions, e.g., overloads must have different
parameter-type-lists from each other.

When calling an overloaded function in C, we follow the same
overloading rules as C++, with three extensions to the set of standard
conversions:

  - A value of a given struct or union type T can be converted to the
    type T. This is just the identity conversion. (In C++, this would
    go through a copy constructor).
  - A value of pointer type T* can be converted to a value of type U*
    if T and U are compatible types. This conversion has Conversion
    rank (it's considered a pointer conversion in C).
  - A value of type T can be converted to a value of type U if T and U
    are compatible (and are not both pointer types). This conversion
    has Conversion rank (it's considered to be a new kind of
    conversion unique to C, a "compatible" conversion).

Known defects (and, therefore, next steps):
  1) The standard-conversion handling does not understand conversions
  involving _Complex or vector extensions, so it is likely to get
  these wrong. We need to add these conversions.
  2) All overloadable functions with the same name will have the same
  linkage name, which means we'll get a collision in the linker (if
  not sooner). We'll need to mangle the names of these functions.


Modified:
    cfe/trunk/include/clang/AST/Attr.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
    cfe/trunk/include/clang/Parse/AttributeList.h
    cfe/trunk/lib/Parse/AttributeList.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaOverload.h

Modified: cfe/trunk/include/clang/AST/Attr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=64336&r1=64335&r2=64336&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Attr.h (original)
+++ cfe/trunk/include/clang/AST/Attr.h Wed Feb 11 17:02:49 2009
@@ -43,6 +43,7 @@
     NoThrow,
     ObjCGC,
     ObjCNSObject,
+    Overloadable, // Clang-specific
     Packed,
     StdCall,
     TransparentUnion,
@@ -429,6 +430,14 @@
 static bool classof(const ObjCNSObjectAttr *A) { return true; }
 };
   
+class OverloadableAttr : public Attr {
+public:
+  OverloadableAttr() : Attr(Overloadable) { }
+
+  static bool classof(const Attr *A) { return A->getKind() == Overloadable; }
+  static bool classof(const OverloadableAttr *) { return true; }
+};
+
 class BlocksAttr : public Attr {
 public:
   enum BlocksAttrTypes {

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=64336&r1=64335&r2=64336&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Wed Feb 11 17:02:49 2009
@@ -393,6 +393,12 @@
 // Clang-Specific Attributes
 DIAG(err_attribute_iboutlet_non_ivar, ERROR,
      "'iboutlet' attribute can only be applied to instance variables")
+DIAG(err_attribute_overloadable_not_function, ERROR,
+     "'overloadable' attribute can only be applied to a function")
+DIAG(err_attribute_overloadable_missing, ERROR,
+     "overloaded function %0 must have the 'overloadable' attribute")
+DIAG(note_attribute_overloadable_prev_overload, NOTE,
+     "previous overload of function is here")
 
 // Function Parameter Semantic Analysis.
 DIAG(err_param_with_void_type, ERROR,

Modified: cfe/trunk/include/clang/Parse/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/AttributeList.h?rev=64336&r1=64335&r2=64336&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/AttributeList.h (original)
+++ cfe/trunk/include/clang/Parse/AttributeList.h Wed Feb 11 17:02:49 2009
@@ -62,6 +62,7 @@
     AT_nonnull,
     AT_noreturn,
     AT_nothrow,
+    AT_overloadable,      // Clang-specific
     AT_packed,
     AT_pure,
     AT_stdcall,

Modified: cfe/trunk/lib/Parse/AttributeList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/AttributeList.cpp?rev=64336&r1=64335&r2=64336&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/AttributeList.cpp (original)
+++ cfe/trunk/lib/Parse/AttributeList.cpp Wed Feb 11 17:02:49 2009
@@ -98,6 +98,9 @@
     if (!memcmp(Str, "constructor", 11)) return AT_constructor;
     if (!memcmp(Str, "unavailable", 11)) return AT_unavailable;
     break;
+  case 12:
+    if (!memcmp(Str, "overloadable", 12)) return AT_overloadable;
+    break;
   case 13:
     if (!memcmp(Str, "address_space", 13)) return AT_address_space;
     if (!memcmp(Str, "always_inline", 13)) return AT_always_inline;

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=64336&r1=64335&r2=64336&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Feb 11 17:02:49 2009
@@ -113,6 +113,25 @@
   CurContext = getContainingDC(CurContext);
 }
 
+/// \brief Determine whether we allow overloading of the function
+/// PrevDecl with another declaration.
+///
+/// This routine determines whether overloading is possible, not
+/// whether some new function is actually an overload. It will return
+/// true in C++ (where we can always provide overloads) or, as an
+/// extension, in C when the previous function is already an
+/// overloaded function declaration or has the "overloadable"
+/// attribute.
+static bool AllowOverloadingOfFunction(Decl *PrevDecl, ASTContext &Context) {
+  if (Context.getLangOptions().CPlusPlus)
+    return true;
+
+  if (isa<OverloadedFunctionDecl>(PrevDecl))
+    return true;
+
+  return PrevDecl->getAttr<OverloadableAttr>() != 0;
+}
+
 /// Add this decl to the scope shadowed decl chains.
 void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
   // Move up the scope chain until we find the nearest enclosing
@@ -173,7 +192,8 @@
         return;
       }
     }
-  } else if (getLangOptions().CPlusPlus && isa<FunctionDecl>(D)) {
+  } else if (isa<FunctionDecl>(D) &&
+             AllowOverloadingOfFunction(D, Context)) {
     // We are pushing the name of a function, which might be an
     // overloaded name.
     FunctionDecl *FD = cast<FunctionDecl>(D);
@@ -1637,15 +1657,16 @@
     
   // Merge the decl with the existing one if appropriate. Since C functions
   // are in a flat namespace, make sure we consider decls in outer scopes.
+  bool OverloadableAttrRequired = false;
   bool Redeclaration = false;
   if (PrevDecl &&
       (!getLangOptions().CPlusPlus||isDeclInScope(PrevDecl, DC, S))) {
-    // If C++, determine whether NewFD is an overload of PrevDecl or
+    // Determine whether NewFD is an overload of PrevDecl or
     // a declaration that requires merging. If it's an overload,
     // there's no more work to do here; we'll just add the new
     // function to the scope.
     OverloadedFunctionDecl::function_iterator MatchedDecl;
-    if (!getLangOptions().CPlusPlus ||
+    if (!AllowOverloadingOfFunction(PrevDecl, Context) || 
         !IsOverload(NewFD, PrevDecl, MatchedDecl)) {
       Decl *OldDecl = PrevDecl;
 
@@ -1672,6 +1693,12 @@
         }
       }
     }
+
+    // If we're in C, this new declaration better have the
+    // "overloadable" attribute on it.
+    if (!getLangOptions().CPlusPlus && 
+        PrevDecl->getAttr<OverloadableAttr>())
+      OverloadableAttrRequired = true;
   }
 
   if (D.getCXXScopeSpec().isSet() &&
@@ -1712,6 +1739,17 @@
   // (for example to check for conflicts, etc).
   ProcessDeclAttributes(NewFD, D);
 
+  if (OverloadableAttrRequired && !NewFD->getAttr<OverloadableAttr>()) {
+    // If a function name is overloadable in C, then every function
+    // with that name must be marked "overloadable".
+    Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
+      << NewFD;
+    if (PrevDecl)
+      Diag(PrevDecl->getLocation(), 
+           diag::note_attribute_overloadable_prev_overload);
+    NewFD->addAttr(new OverloadableAttr);
+  }
+
   if (getLangOptions().CPlusPlus) {
     // In C++, check default arguments now that we have merged decls. Unless
     // the lexical context is the class, because in this case this is done

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=64336&r1=64335&r2=64336&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed Feb 11 17:02:49 2009
@@ -593,6 +593,21 @@
   d->addAttr(new ObjCNSObjectAttr);
 }
 
+static void 
+HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  if (!isa<FunctionDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function);
+    return;
+  }
+
+  D->addAttr(new OverloadableAttr);
+}
+
 static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
   if (!Attr.getParameterName()) {    
     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
@@ -1301,6 +1316,7 @@
     HandleTransparentUnionAttr(D, Attr, S);
     break;
   case AttributeList::AT_objc_gc:     HandleObjCGCAttr    (D, Attr, S); break;
+  case AttributeList::AT_overloadable:HandleOverloadableAttr(D, Attr, S); break;
   case AttributeList::AT_nsobject:    HandleObjCNSObject  (D, Attr, S); break;
   case AttributeList::AT_blocks:      HandleBlocksAttr    (D, Attr, S); break;
   case AttributeList::AT_sentinel:    HandleSentinelAttr  (D, Attr, S); break;

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=64336&r1=64335&r2=64336&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Feb 11 17:02:49 2009
@@ -1909,12 +1909,16 @@
     Ovl = dyn_cast<OverloadedFunctionDecl>(DRExpr->getDecl());
   }
 
-  if (getLangOptions().CPlusPlus && (FDecl || Ovl || UnqualifiedName)) {
+  if (Ovl || (getLangOptions().CPlusPlus && (FDecl || UnqualifiedName))) {
     // We don't perform ADL for builtins.
     if (FDecl && FDecl->getIdentifier() && 
         FDecl->getIdentifier()->getBuiltinID())
       ADL = false;
 
+    // We don't perform ADL in C.
+    if (!getLangOptions().CPlusPlus)
+      ADL = false;
+
     if (Ovl || ADL) {
       FDecl = ResolveOverloadedCallFn(Fn, DRExpr? DRExpr->getDecl() : 0, 
                                       UnqualifiedName, LParenLoc, Args, 

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=64336&r1=64335&r2=64336&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Feb 11 17:02:49 2009
@@ -809,6 +809,8 @@
   case ICK_Integral_Conversion:
   case ICK_Floating_Conversion:
   case ICK_Floating_Integral:
+  case ICK_Compatible_Conversion:
+      // FIXME: Go deeper to get the unqualified type!
     FromType = ToType.getUnqualifiedType();
     ImpCastExprToType(From, FromType);
     break;

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=64336&r1=64335&r2=64336&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Wed Feb 11 17:02:49 2009
@@ -776,8 +776,29 @@
     for (IdentifierResolver::iterator I = IdResolver.begin(Name),
                                    IEnd = IdResolver.end(); 
          I != IEnd; ++I)
-      if ((*I)->isInIdentifierNamespace(IDNS))
+      if ((*I)->isInIdentifierNamespace(IDNS)) {
+        if ((*I)->getAttr<OverloadableAttr>()) {
+          // If this declaration has the "overloadable" attribute, we
+          // might have a set of overloaded functions.
+
+          // Figure out what scope the identifier is in.
+          while (!(S->getFlags() & Scope::DeclScope) || !S->isDeclScope(*I))
+            S = S->getParent();
+
+          // Find the last declaration in this scope (with the same
+          // name, naturally).
+          IdentifierResolver::iterator LastI = I;
+          for (++LastI; LastI != IEnd; ++LastI) {
+            if (!S->isDeclScope(*LastI))
+              break;
+          }
+
+          return LookupResult::CreateLookupResult(Context, I, LastI);
+        }
+
+        // We have a single lookup result.
         return LookupResult::CreateLookupResult(Context, *I);
+      }
   } else {
     // Perform C++ unqualified name lookup.
     std::pair<bool, LookupResult> MaybeResult =

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=64336&r1=64335&r2=64336&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Feb 11 17:02:49 2009
@@ -45,6 +45,7 @@
     ICC_Conversion,
     ICC_Conversion,
     ICC_Conversion,
+    ICC_Conversion,
     ICC_Conversion
   };
   return Category[(int)Kind];
@@ -68,6 +69,7 @@
     ICR_Conversion,
     ICR_Conversion,
     ICR_Conversion,
+    ICR_Conversion,
     ICR_Conversion
   };
   return Rank[(int)Kind];
@@ -90,6 +92,7 @@
     "Pointer conversion",
     "Pointer-to-member conversion",
     "Boolean conversion",
+    "Compatible-types conversion",
     "Derived-to-base conversion"
   };
   return Name[Kind];
@@ -371,7 +374,8 @@
   ImplicitConversionSequence ICS;
   if (IsStandardConversion(From, ToType, ICS.Standard))
     ICS.ConversionKind = ImplicitConversionSequence::StandardConversion;
-  else if (IsUserDefinedConversion(From, ToType, ICS.UserDefined, 
+  else if (getLangOptions().CPlusPlus &&
+           IsUserDefinedConversion(From, ToType, ICS.UserDefined, 
                                    !SuppressUserConversions, AllowExplicit)) {
     ICS.ConversionKind = ImplicitConversionSequence::UserDefinedConversion;
     // C++ [over.ics.user]p4:
@@ -429,10 +433,6 @@
 {
   QualType FromType = From->getType();
 
-  // There are no standard conversions for class types, so abort early.
-  if (FromType->isRecordType() || ToType->isRecordType())
-    return false;
-
   // Standard conversions (C++ [conv])
   SCS.setAsIdentityConversion();
   SCS.Deprecated = false;
@@ -440,6 +440,15 @@
   SCS.FromTypePtr = FromType.getAsOpaquePtr();
   SCS.CopyConstructor = 0;
 
+  // There are no standard conversions for class types in C++, so
+  // abort early. When overloading in C, however, we do permit 
+  if (FromType->isRecordType() || ToType->isRecordType()) {
+    if (getLangOptions().CPlusPlus)
+      return false;
+
+    // When we're overloading in C, we allow, as standard conversions, 
+  }
+
   // The first conversion can be an lvalue-to-rvalue conversion,
   // array-to-pointer conversion, or function-to-pointer conversion
   // (C++ 4p1).
@@ -455,7 +464,10 @@
 
     // If T is a non-class type, the type of the rvalue is the
     // cv-unqualified version of T. Otherwise, the type of the rvalue
-    // is T (C++ 4.1p1).
+    // is T (C++ 4.1p1). C++ can't get here with class types; in C, we
+    // just strip the qualifiers because they don't matter.
+
+    // FIXME: Doesn't see through to qualifiers behind a typedef!
     FromType = FromType.getUnqualifiedType();
   }
   // Array-to-pointer conversion (C++ 4.2)
@@ -522,9 +534,10 @@
   // point promotion, integral conversion, floating point conversion,
   // floating-integral conversion, pointer conversion,
   // pointer-to-member conversion, or boolean conversion (C++ 4p1).
+  // For overloading in C, this can also be a "compatible-type"
+  // conversion.
   bool IncompatibleObjC = false;
-  if (Context.getCanonicalType(FromType).getUnqualifiedType() ==
-      Context.getCanonicalType(ToType).getUnqualifiedType()) {
+  if (Context.hasSameUnqualifiedType(FromType, ToType)) {
     // The unqualified versions of the types are the same: there's no
     // conversion to do.
     SCS.Second = ICK_Identity;
@@ -580,6 +593,11 @@
             FromType->isMemberPointerType())) {
     SCS.Second = ICK_Boolean_Conversion;
     FromType = Context.BoolTy;
+  }
+  // Compatible conversions (Clang extension for C function overloading)
+  else if (!getLangOptions().CPlusPlus && 
+           Context.typesAreCompatible(ToType, FromType)) {
+    SCS.Second = ICK_Compatible_Conversion;
   } else {
     // No second conversion required.
     SCS.Second = ICK_Identity;
@@ -847,6 +865,16 @@
     return true;
   }
 
+  // When we're overloading in C, we allow a special kind of pointer
+  // conversion for compatible-but-not-identical pointee types.
+  if (!getLangOptions().CPlusPlus && 
+      Context.typesAreCompatible(FromPointeeType, ToPointeeType)) {
+    ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, 
+                                                       ToPointeeType,
+                                                       ToType, Context);    
+    return true;
+  }
+
   // C++ [conv.ptr]p3:
   // 
   //   An rvalue of type "pointer to cv D," where D is a class type,
@@ -860,7 +888,8 @@
   //
   // Note that we do not check for ambiguity or inaccessibility
   // here. That is handled by CheckPointerConversion.
-  if (FromPointeeType->isRecordType() && ToPointeeType->isRecordType() &&
+  if (getLangOptions().CPlusPlus &&
+      FromPointeeType->isRecordType() && ToPointeeType->isRecordType() &&
       IsDerivedFrom(FromPointeeType, ToPointeeType)) {
     ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, 
                                                        ToPointeeType,
@@ -1756,18 +1785,7 @@
 ImplicitConversionSequence 
 Sema::TryCopyInitialization(Expr *From, QualType ToType, 
                             bool SuppressUserConversions) {
-  if (!getLangOptions().CPlusPlus) {
-    // In C, copy initialization is the same as performing an assignment.
-    AssignConvertType ConvTy =
-      CheckSingleAssignmentConstraints(ToType, From);
-    ImplicitConversionSequence ICS;
-    if (getLangOptions().NoExtensions? ConvTy != Compatible
-                                     : ConvTy == Incompatible)
-      ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
-    else
-      ICS.ConversionKind = ImplicitConversionSequence::StandardConversion;
-    return ICS;
-  } else if (ToType->isReferenceType()) {
+  if (ToType->isReferenceType()) {
     ImplicitConversionSequence ICS;
     CheckReferenceInit(From, ToType, &ICS, SuppressUserConversions);
     return ICS;

Modified: cfe/trunk/lib/Sema/SemaOverload.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.h?rev=64336&r1=64335&r2=64336&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.h (original)
+++ cfe/trunk/lib/Sema/SemaOverload.h Wed Feb 11 17:02:49 2009
@@ -26,21 +26,22 @@
   /// match with Table 9 of (C++ 13.3.3.1.1) and are listed such that
   /// better conversion kinds have smaller values.
   enum ImplicitConversionKind {
-    ICK_Identity = 0,        ///< Identity conversion (no conversion)
-    ICK_Lvalue_To_Rvalue,    ///< Lvalue-to-rvalue conversion (C++ 4.1)
-    ICK_Array_To_Pointer,    ///< Array-to-pointer conversion (C++ 4.2)
-    ICK_Function_To_Pointer, ///< Function-to-pointer (C++ 4.3)
-    ICK_Qualification,       ///< Qualification conversions (C++ 4.4)
-    ICK_Integral_Promotion,  ///< Integral promotions (C++ 4.5)
-    ICK_Floating_Promotion,  ///< Floating point promotions (C++ 4.6)
-    ICK_Integral_Conversion, ///< Integral conversions (C++ 4.7)
-    ICK_Floating_Conversion, ///< Floating point conversions (C++ 4.8)
-    ICK_Floating_Integral,   ///< Floating-integral conversions (C++ 4.9)
-    ICK_Pointer_Conversion,  ///< Pointer conversions (C++ 4.10)
-    ICK_Pointer_Member,      ///< Pointer-to-member conversions (C++ 4.11)
-    ICK_Boolean_Conversion,  ///< Boolean conversions (C++ 4.12)
-    ICK_Derived_To_Base,     ///< Derived-to-base (C++ [over.best.ics][)
-    ICK_Num_Conversion_Kinds ///< The number of conversion kinds
+    ICK_Identity = 0,          ///< Identity conversion (no conversion)
+    ICK_Lvalue_To_Rvalue,      ///< Lvalue-to-rvalue conversion (C++ 4.1)
+    ICK_Array_To_Pointer,      ///< Array-to-pointer conversion (C++ 4.2)
+    ICK_Function_To_Pointer,   ///< Function-to-pointer (C++ 4.3)
+    ICK_Qualification,         ///< Qualification conversions (C++ 4.4)
+    ICK_Integral_Promotion,    ///< Integral promotions (C++ 4.5)
+    ICK_Floating_Promotion,    ///< Floating point promotions (C++ 4.6)
+    ICK_Integral_Conversion,   ///< Integral conversions (C++ 4.7)
+    ICK_Floating_Conversion,   ///< Floating point conversions (C++ 4.8)
+    ICK_Floating_Integral,     ///< Floating-integral conversions (C++ 4.9)
+    ICK_Pointer_Conversion,    ///< Pointer conversions (C++ 4.10)
+    ICK_Pointer_Member,        ///< Pointer-to-member conversions (C++ 4.11)
+    ICK_Boolean_Conversion,    ///< Boolean conversions (C++ 4.12)
+    ICK_Compatible_Conversion, ///< Conversions between compatible types in C99
+    ICK_Derived_To_Base,       ///< Derived-to-base (C++ [over.best.ics])
+    ICK_Num_Conversion_Kinds   ///< The number of conversion kinds
   };
 
   /// ImplicitConversionCategory - The category of an implicit





More information about the cfe-commits mailing list