Home | History | Annotate | Download | only in Sema
      1 //===--- SemaExceptionSpec.cpp - C++ Exception Specifications ---*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file provides Sema routines for C++ exception specification testing.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "clang/Sema/SemaInternal.h"
     15 #include "clang/AST/CXXInheritance.h"
     16 #include "clang/AST/Expr.h"
     17 #include "clang/AST/ExprCXX.h"
     18 #include "clang/AST/TypeLoc.h"
     19 #include "clang/Lex/Preprocessor.h"
     20 #include "clang/Basic/Diagnostic.h"
     21 #include "clang/Basic/SourceManager.h"
     22 #include "llvm/ADT/SmallPtrSet.h"
     23 #include "llvm/ADT/SmallString.h"
     24 
     25 namespace clang {
     26 
     27 static const FunctionProtoType *GetUnderlyingFunction(QualType T)
     28 {
     29   if (const PointerType *PtrTy = T->getAs<PointerType>())
     30     T = PtrTy->getPointeeType();
     31   else if (const ReferenceType *RefTy = T->getAs<ReferenceType>())
     32     T = RefTy->getPointeeType();
     33   else if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
     34     T = MPTy->getPointeeType();
     35   return T->getAs<FunctionProtoType>();
     36 }
     37 
     38 /// CheckSpecifiedExceptionType - Check if the given type is valid in an
     39 /// exception specification. Incomplete types, or pointers to incomplete types
     40 /// other than void are not allowed.
     41 bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) {
     42 
     43   // This check (and the similar one below) deals with issue 437, that changes
     44   // C++ 9.2p2 this way:
     45   // Within the class member-specification, the class is regarded as complete
     46   // within function bodies, default arguments, exception-specifications, and
     47   // constructor ctor-initializers (including such things in nested classes).
     48   if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined())
     49     return false;
     50 
     51   // C++ 15.4p2: A type denoted in an exception-specification shall not denote
     52   //   an incomplete type.
     53   if (RequireCompleteType(Range.getBegin(), T,
     54       PDiag(diag::err_incomplete_in_exception_spec) << /*direct*/0 << Range))
     55     return true;
     56 
     57   // C++ 15.4p2: A type denoted in an exception-specification shall not denote
     58   //   an incomplete type a pointer or reference to an incomplete type, other
     59   //   than (cv) void*.
     60   int kind;
     61   if (const PointerType* IT = T->getAs<PointerType>()) {
     62     T = IT->getPointeeType();
     63     kind = 1;
     64   } else if (const ReferenceType* IT = T->getAs<ReferenceType>()) {
     65     T = IT->getPointeeType();
     66     kind = 2;
     67   } else
     68     return false;
     69 
     70   // Again as before
     71   if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined())
     72     return false;
     73 
     74   if (!T->isVoidType() && RequireCompleteType(Range.getBegin(), T,
     75       PDiag(diag::err_incomplete_in_exception_spec) << kind << Range))
     76     return true;
     77 
     78   return false;
     79 }
     80 
     81 /// CheckDistantExceptionSpec - Check if the given type is a pointer or pointer
     82 /// to member to a function with an exception specification. This means that
     83 /// it is invalid to add another level of indirection.
     84 bool Sema::CheckDistantExceptionSpec(QualType T) {
     85   if (const PointerType *PT = T->getAs<PointerType>())
     86     T = PT->getPointeeType();
     87   else if (const MemberPointerType *PT = T->getAs<MemberPointerType>())
     88     T = PT->getPointeeType();
     89   else
     90     return false;
     91 
     92   const FunctionProtoType *FnT = T->getAs<FunctionProtoType>();
     93   if (!FnT)
     94     return false;
     95 
     96   return FnT->hasExceptionSpec();
     97 }
     98 
     99 const FunctionProtoType *
    100 Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) {
    101   // FIXME: If FD is a special member, we should delay computing its exception
    102   // specification until this point.
    103   if (FPT->getExceptionSpecType() != EST_Uninstantiated)
    104     return FPT;
    105 
    106   FunctionDecl *SourceDecl = FPT->getExceptionSpecDecl();
    107   const FunctionProtoType *SourceFPT =
    108       SourceDecl->getType()->castAs<FunctionProtoType>();
    109 
    110   if (SourceFPT->getExceptionSpecType() != EST_Uninstantiated)
    111     return SourceFPT;
    112 
    113   // Instantiate the exception specification now.
    114   InstantiateExceptionSpec(Loc, SourceDecl);
    115 
    116   return SourceDecl->getType()->castAs<FunctionProtoType>();
    117 }
    118 
    119 bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
    120   OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator();
    121   bool IsOperatorNew = OO == OO_New || OO == OO_Array_New;
    122   bool MissingExceptionSpecification = false;
    123   bool MissingEmptyExceptionSpecification = false;
    124   unsigned DiagID = diag::err_mismatched_exception_spec;
    125   if (getLangOpts().MicrosoftExt)
    126     DiagID = diag::warn_mismatched_exception_spec;
    127 
    128   if (!CheckEquivalentExceptionSpec(PDiag(DiagID),
    129                                     PDiag(diag::note_previous_declaration),
    130                                     Old->getType()->getAs<FunctionProtoType>(),
    131                                     Old->getLocation(),
    132                                     New->getType()->getAs<FunctionProtoType>(),
    133                                     New->getLocation(),
    134                                     &MissingExceptionSpecification,
    135                                     &MissingEmptyExceptionSpecification,
    136                                     /*AllowNoexceptAllMatchWithNoSpec=*/true,
    137                                     IsOperatorNew))
    138     return false;
    139 
    140   // The failure was something other than an empty exception
    141   // specification; return an error.
    142   if (!MissingExceptionSpecification && !MissingEmptyExceptionSpecification)
    143     return true;
    144 
    145   const FunctionProtoType *NewProto
    146     = New->getType()->getAs<FunctionProtoType>();
    147 
    148   // The new function declaration is only missing an empty exception
    149   // specification "throw()". If the throw() specification came from a
    150   // function in a system header that has C linkage, just add an empty
    151   // exception specification to the "new" declaration. This is an
    152   // egregious workaround for glibc, which adds throw() specifications
    153   // to many libc functions as an optimization. Unfortunately, that
    154   // optimization isn't permitted by the C++ standard, so we're forced
    155   // to work around it here.
    156   if (MissingEmptyExceptionSpecification && NewProto &&
    157       (Old->getLocation().isInvalid() ||
    158        Context.getSourceManager().isInSystemHeader(Old->getLocation())) &&
    159       Old->isExternC()) {
    160     FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
    161     EPI.ExceptionSpecType = EST_DynamicNone;
    162     QualType NewType = Context.getFunctionType(NewProto->getResultType(),
    163                                                NewProto->arg_type_begin(),
    164                                                NewProto->getNumArgs(),
    165                                                EPI);
    166     New->setType(NewType);
    167     return false;
    168   }
    169 
    170   if (MissingExceptionSpecification && NewProto) {
    171     const FunctionProtoType *OldProto
    172       = Old->getType()->getAs<FunctionProtoType>();
    173 
    174     FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
    175     EPI.ExceptionSpecType = OldProto->getExceptionSpecType();
    176     if (EPI.ExceptionSpecType == EST_Dynamic) {
    177       EPI.NumExceptions = OldProto->getNumExceptions();
    178       EPI.Exceptions = OldProto->exception_begin();
    179     } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
    180       // FIXME: We can't just take the expression from the old prototype. It
    181       // likely contains references to the old prototype's parameters.
    182     }
    183 
    184     // Update the type of the function with the appropriate exception
    185     // specification.
    186     QualType NewType = Context.getFunctionType(NewProto->getResultType(),
    187                                                NewProto->arg_type_begin(),
    188                                                NewProto->getNumArgs(),
    189                                                EPI);
    190     New->setType(NewType);
    191 
    192     // If exceptions are disabled, suppress the warning about missing
    193     // exception specifications for new and delete operators.
    194     if (!getLangOpts().CXXExceptions) {
    195       switch (New->getDeclName().getCXXOverloadedOperator()) {
    196       case OO_New:
    197       case OO_Array_New:
    198       case OO_Delete:
    199       case OO_Array_Delete:
    200         if (New->getDeclContext()->isTranslationUnit())
    201           return false;
    202         break;
    203 
    204       default:
    205         break;
    206       }
    207     }
    208 
    209     // Warn about the lack of exception specification.
    210     SmallString<128> ExceptionSpecString;
    211     llvm::raw_svector_ostream OS(ExceptionSpecString);
    212     switch (OldProto->getExceptionSpecType()) {
    213     case EST_DynamicNone:
    214       OS << "throw()";
    215       break;
    216 
    217     case EST_Dynamic: {
    218       OS << "throw(";
    219       bool OnFirstException = true;
    220       for (FunctionProtoType::exception_iterator E = OldProto->exception_begin(),
    221                                               EEnd = OldProto->exception_end();
    222            E != EEnd;
    223            ++E) {
    224         if (OnFirstException)
    225           OnFirstException = false;
    226         else
    227           OS << ", ";
    228 
    229         OS << E->getAsString(getPrintingPolicy());
    230       }
    231       OS << ")";
    232       break;
    233     }
    234 
    235     case EST_BasicNoexcept:
    236       OS << "noexcept";
    237       break;
    238 
    239     case EST_ComputedNoexcept:
    240       OS << "noexcept(";
    241       OldProto->getNoexceptExpr()->printPretty(OS, Context, 0,
    242                                                getPrintingPolicy());
    243       OS << ")";
    244       break;
    245 
    246     default:
    247       llvm_unreachable("This spec type is compatible with none.");
    248     }
    249     OS.flush();
    250 
    251     SourceLocation FixItLoc;
    252     if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) {
    253       TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
    254       if (const FunctionTypeLoc *FTLoc = dyn_cast<FunctionTypeLoc>(&TL))
    255         FixItLoc = PP.getLocForEndOfToken(FTLoc->getLocalRangeEnd());
    256     }
    257 
    258     if (FixItLoc.isInvalid())
    259       Diag(New->getLocation(), diag::warn_missing_exception_specification)
    260         << New << OS.str();
    261     else {
    262       // FIXME: This will get more complicated with C++0x
    263       // late-specified return types.
    264       Diag(New->getLocation(), diag::warn_missing_exception_specification)
    265         << New << OS.str()
    266         << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str());
    267     }
    268 
    269     if (!Old->getLocation().isInvalid())
    270       Diag(Old->getLocation(), diag::note_previous_declaration);
    271 
    272     return false;
    273   }
    274 
    275   Diag(New->getLocation(), DiagID);
    276   Diag(Old->getLocation(), diag::note_previous_declaration);
    277   return true;
    278 }
    279 
    280 /// CheckEquivalentExceptionSpec - Check if the two types have equivalent
    281 /// exception specifications. Exception specifications are equivalent if
    282 /// they allow exactly the same set of exception types. It does not matter how
    283 /// that is achieved. See C++ [except.spec]p2.
    284 bool Sema::CheckEquivalentExceptionSpec(
    285     const FunctionProtoType *Old, SourceLocation OldLoc,
    286     const FunctionProtoType *New, SourceLocation NewLoc) {
    287   unsigned DiagID = diag::err_mismatched_exception_spec;
    288   if (getLangOpts().MicrosoftExt)
    289     DiagID = diag::warn_mismatched_exception_spec;
    290   return CheckEquivalentExceptionSpec(
    291                                       PDiag(DiagID),
    292                                       PDiag(diag::note_previous_declaration),
    293                                       Old, OldLoc, New, NewLoc);
    294 }
    295 
    296 /// CheckEquivalentExceptionSpec - Check if the two types have compatible
    297 /// exception specifications. See C++ [except.spec]p3.
    298 bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
    299                                         const PartialDiagnostic & NoteID,
    300                                         const FunctionProtoType *Old,
    301                                         SourceLocation OldLoc,
    302                                         const FunctionProtoType *New,
    303                                         SourceLocation NewLoc,
    304                                         bool *MissingExceptionSpecification,
    305                                         bool*MissingEmptyExceptionSpecification,
    306                                         bool AllowNoexceptAllMatchWithNoSpec,
    307                                         bool IsOperatorNew) {
    308   // Just completely ignore this under -fno-exceptions.
    309   if (!getLangOpts().CXXExceptions)
    310     return false;
    311 
    312   if (MissingExceptionSpecification)
    313     *MissingExceptionSpecification = false;
    314 
    315   if (MissingEmptyExceptionSpecification)
    316     *MissingEmptyExceptionSpecification = false;
    317 
    318   Old = ResolveExceptionSpec(NewLoc, Old);
    319   if (!Old)
    320     return false;
    321   New = ResolveExceptionSpec(NewLoc, New);
    322   if (!New)
    323     return false;
    324 
    325   // C++0x [except.spec]p3: Two exception-specifications are compatible if:
    326   //   - both are non-throwing, regardless of their form,
    327   //   - both have the form noexcept(constant-expression) and the constant-
    328   //     expressions are equivalent,
    329   //   - both are dynamic-exception-specifications that have the same set of
    330   //     adjusted types.
    331   //
    332   // C++0x [except.spec]p12: An exception-specifcation is non-throwing if it is
    333   //   of the form throw(), noexcept, or noexcept(constant-expression) where the
    334   //   constant-expression yields true.
    335   //
    336   // C++0x [except.spec]p4: If any declaration of a function has an exception-
    337   //   specifier that is not a noexcept-specification allowing all exceptions,
    338   //   all declarations [...] of that function shall have a compatible
    339   //   exception-specification.
    340   //
    341   // That last point basically means that noexcept(false) matches no spec.
    342   // It's considered when AllowNoexceptAllMatchWithNoSpec is true.
    343 
    344   ExceptionSpecificationType OldEST = Old->getExceptionSpecType();
    345   ExceptionSpecificationType NewEST = New->getExceptionSpecType();
    346 
    347   assert(OldEST != EST_Delayed && NewEST != EST_Delayed &&
    348          OldEST != EST_Uninstantiated && NewEST != EST_Uninstantiated &&
    349          "Shouldn't see unknown exception specifications here");
    350 
    351   // Shortcut the case where both have no spec.
    352   if (OldEST == EST_None && NewEST == EST_None)
    353     return false;
    354 
    355   FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(Context);
    356   FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(Context);
    357   if (OldNR == FunctionProtoType::NR_BadNoexcept ||
    358       NewNR == FunctionProtoType::NR_BadNoexcept)
    359     return false;
    360 
    361   // Dependent noexcept specifiers are compatible with each other, but nothing
    362   // else.
    363   // One noexcept is compatible with another if the argument is the same
    364   if (OldNR == NewNR &&
    365       OldNR != FunctionProtoType::NR_NoNoexcept &&
    366       NewNR != FunctionProtoType::NR_NoNoexcept)
    367     return false;
    368   if (OldNR != NewNR &&
    369       OldNR != FunctionProtoType::NR_NoNoexcept &&
    370       NewNR != FunctionProtoType::NR_NoNoexcept) {
    371     Diag(NewLoc, DiagID);
    372     if (NoteID.getDiagID() != 0)
    373       Diag(OldLoc, NoteID);
    374     return true;
    375   }
    376 
    377   // The MS extension throw(...) is compatible with itself.
    378   if (OldEST == EST_MSAny && NewEST == EST_MSAny)
    379     return false;
    380 
    381   // It's also compatible with no spec.
    382   if ((OldEST == EST_None && NewEST == EST_MSAny) ||
    383       (OldEST == EST_MSAny && NewEST == EST_None))
    384     return false;
    385 
    386   // It's also compatible with noexcept(false).
    387   if (OldEST == EST_MSAny && NewNR == FunctionProtoType::NR_Throw)
    388     return false;
    389   if (NewEST == EST_MSAny && OldNR == FunctionProtoType::NR_Throw)
    390     return false;
    391 
    392   // As described above, noexcept(false) matches no spec only for functions.
    393   if (AllowNoexceptAllMatchWithNoSpec) {
    394     if (OldEST == EST_None && NewNR == FunctionProtoType::NR_Throw)
    395       return false;
    396     if (NewEST == EST_None && OldNR == FunctionProtoType::NR_Throw)
    397       return false;
    398   }
    399 
    400   // Any non-throwing specifications are compatible.
    401   bool OldNonThrowing = OldNR == FunctionProtoType::NR_Nothrow ||
    402                         OldEST == EST_DynamicNone;
    403   bool NewNonThrowing = NewNR == FunctionProtoType::NR_Nothrow ||
    404                         NewEST == EST_DynamicNone;
    405   if (OldNonThrowing && NewNonThrowing)
    406     return false;
    407 
    408   // As a special compatibility feature, under C++0x we accept no spec and
    409   // throw(std::bad_alloc) as equivalent for operator new and operator new[].
    410   // This is because the implicit declaration changed, but old code would break.
    411   if (getLangOpts().CPlusPlus0x && IsOperatorNew) {
    412     const FunctionProtoType *WithExceptions = 0;
    413     if (OldEST == EST_None && NewEST == EST_Dynamic)
    414       WithExceptions = New;
    415     else if (OldEST == EST_Dynamic && NewEST == EST_None)
    416       WithExceptions = Old;
    417     if (WithExceptions && WithExceptions->getNumExceptions() == 1) {
    418       // One has no spec, the other throw(something). If that something is
    419       // std::bad_alloc, all conditions are met.
    420       QualType Exception = *WithExceptions->exception_begin();
    421       if (CXXRecordDecl *ExRecord = Exception->getAsCXXRecordDecl()) {
    422         IdentifierInfo* Name = ExRecord->getIdentifier();
    423         if (Name && Name->getName() == "bad_alloc") {
    424           // It's called bad_alloc, but is it in std?
    425           DeclContext* DC = ExRecord->getDeclContext();
    426           DC = DC->getEnclosingNamespaceContext();
    427           if (NamespaceDecl* NS = dyn_cast<NamespaceDecl>(DC)) {
    428             IdentifierInfo* NSName = NS->getIdentifier();
    429             DC = DC->getParent();
    430             if (NSName && NSName->getName() == "std" &&
    431                 DC->getEnclosingNamespaceContext()->isTranslationUnit()) {
    432               return false;
    433             }
    434           }
    435         }
    436       }
    437     }
    438   }
    439 
    440   // At this point, the only remaining valid case is two matching dynamic
    441   // specifications. We return here unless both specifications are dynamic.
    442   if (OldEST != EST_Dynamic || NewEST != EST_Dynamic) {
    443     if (MissingExceptionSpecification && Old->hasExceptionSpec() &&
    444         !New->hasExceptionSpec()) {
    445       // The old type has an exception specification of some sort, but
    446       // the new type does not.
    447       *MissingExceptionSpecification = true;
    448 
    449       if (MissingEmptyExceptionSpecification && OldNonThrowing) {
    450         // The old type has a throw() or noexcept(true) exception specification
    451         // and the new type has no exception specification, and the caller asked
    452         // to handle this itself.
    453         *MissingEmptyExceptionSpecification = true;
    454       }
    455 
    456       return true;
    457     }
    458 
    459     Diag(NewLoc, DiagID);
    460     if (NoteID.getDiagID() != 0)
    461       Diag(OldLoc, NoteID);
    462     return true;
    463   }
    464 
    465   assert(OldEST == EST_Dynamic && NewEST == EST_Dynamic &&
    466       "Exception compatibility logic error: non-dynamic spec slipped through.");
    467 
    468   bool Success = true;
    469   // Both have a dynamic exception spec. Collect the first set, then compare
    470   // to the second.
    471   llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes;
    472   for (FunctionProtoType::exception_iterator I = Old->exception_begin(),
    473        E = Old->exception_end(); I != E; ++I)
    474     OldTypes.insert(Context.getCanonicalType(*I).getUnqualifiedType());
    475 
    476   for (FunctionProtoType::exception_iterator I = New->exception_begin(),
    477        E = New->exception_end(); I != E && Success; ++I) {
    478     CanQualType TypePtr = Context.getCanonicalType(*I).getUnqualifiedType();
    479     if(OldTypes.count(TypePtr))
    480       NewTypes.insert(TypePtr);
    481     else
    482       Success = false;
    483   }
    484 
    485   Success = Success && OldTypes.size() == NewTypes.size();
    486 
    487   if (Success) {
    488     return false;
    489   }
    490   Diag(NewLoc, DiagID);
    491   if (NoteID.getDiagID() != 0)
    492     Diag(OldLoc, NoteID);
    493   return true;
    494 }
    495 
    496 /// CheckExceptionSpecSubset - Check whether the second function type's
    497 /// exception specification is a subset (or equivalent) of the first function
    498 /// type. This is used by override and pointer assignment checks.
    499 bool Sema::CheckExceptionSpecSubset(
    500     const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
    501     const FunctionProtoType *Superset, SourceLocation SuperLoc,
    502     const FunctionProtoType *Subset, SourceLocation SubLoc) {
    503 
    504   // Just auto-succeed under -fno-exceptions.
    505   if (!getLangOpts().CXXExceptions)
    506     return false;
    507 
    508   // FIXME: As usual, we could be more specific in our error messages, but
    509   // that better waits until we've got types with source locations.
    510 
    511   if (!SubLoc.isValid())
    512     SubLoc = SuperLoc;
    513 
    514   // Resolve the exception specifications, if needed.
    515   Superset = ResolveExceptionSpec(SuperLoc, Superset);
    516   if (!Superset)
    517     return false;
    518   Subset = ResolveExceptionSpec(SubLoc, Subset);
    519   if (!Subset)
    520     return false;
    521 
    522   ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType();
    523 
    524   // If superset contains everything, we're done.
    525   if (SuperEST == EST_None || SuperEST == EST_MSAny)
    526     return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
    527 
    528   // If there are dependent noexcept specs, assume everything is fine. Unlike
    529   // with the equivalency check, this is safe in this case, because we don't
    530   // want to merge declarations. Checks after instantiation will catch any
    531   // omissions we make here.
    532   // We also shortcut checking if a noexcept expression was bad.
    533 
    534   FunctionProtoType::NoexceptResult SuperNR =Superset->getNoexceptSpec(Context);
    535   if (SuperNR == FunctionProtoType::NR_BadNoexcept ||
    536       SuperNR == FunctionProtoType::NR_Dependent)
    537     return false;
    538 
    539   // Another case of the superset containing everything.
    540   if (SuperNR == FunctionProtoType::NR_Throw)
    541     return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
    542 
    543   ExceptionSpecificationType SubEST = Subset->getExceptionSpecType();
    544 
    545   assert(SuperEST != EST_Delayed && SubEST != EST_Delayed &&
    546          SuperEST != EST_Uninstantiated && SubEST != EST_Uninstantiated &&
    547          "Shouldn't see unknown exception specifications here");
    548 
    549   // It does not. If the subset contains everything, we've failed.
    550   if (SubEST == EST_None || SubEST == EST_MSAny) {
    551     Diag(SubLoc, DiagID);
    552     if (NoteID.getDiagID() != 0)
    553       Diag(SuperLoc, NoteID);
    554     return true;
    555   }
    556 
    557   FunctionProtoType::NoexceptResult SubNR = Subset->getNoexceptSpec(Context);
    558   if (SubNR == FunctionProtoType::NR_BadNoexcept ||
    559       SubNR == FunctionProtoType::NR_Dependent)
    560     return false;
    561 
    562   // Another case of the subset containing everything.
    563   if (SubNR == FunctionProtoType::NR_Throw) {
    564     Diag(SubLoc, DiagID);
    565     if (NoteID.getDiagID() != 0)
    566       Diag(SuperLoc, NoteID);
    567     return true;
    568   }
    569 
    570   // If the subset contains nothing, we're done.
    571   if (SubEST == EST_DynamicNone || SubNR == FunctionProtoType::NR_Nothrow)
    572     return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
    573 
    574   // Otherwise, if the superset contains nothing, we've failed.
    575   if (SuperEST == EST_DynamicNone || SuperNR == FunctionProtoType::NR_Nothrow) {
    576     Diag(SubLoc, DiagID);
    577     if (NoteID.getDiagID() != 0)
    578       Diag(SuperLoc, NoteID);
    579     return true;
    580   }
    581 
    582   assert(SuperEST == EST_Dynamic && SubEST == EST_Dynamic &&
    583          "Exception spec subset: non-dynamic case slipped through.");
    584 
    585   // Neither contains everything or nothing. Do a proper comparison.
    586   for (FunctionProtoType::exception_iterator SubI = Subset->exception_begin(),
    587        SubE = Subset->exception_end(); SubI != SubE; ++SubI) {
    588     // Take one type from the subset.
    589     QualType CanonicalSubT = Context.getCanonicalType(*SubI);
    590     // Unwrap pointers and references so that we can do checks within a class
    591     // hierarchy. Don't unwrap member pointers; they don't have hierarchy
    592     // conversions on the pointee.
    593     bool SubIsPointer = false;
    594     if (const ReferenceType *RefTy = CanonicalSubT->getAs<ReferenceType>())
    595       CanonicalSubT = RefTy->getPointeeType();
    596     if (const PointerType *PtrTy = CanonicalSubT->getAs<PointerType>()) {
    597       CanonicalSubT = PtrTy->getPointeeType();
    598       SubIsPointer = true;
    599     }
    600     bool SubIsClass = CanonicalSubT->isRecordType();
    601     CanonicalSubT = CanonicalSubT.getLocalUnqualifiedType();
    602 
    603     CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
    604                        /*DetectVirtual=*/false);
    605 
    606     bool Contained = false;
    607     // Make sure it's in the superset.
    608     for (FunctionProtoType::exception_iterator SuperI =
    609            Superset->exception_begin(), SuperE = Superset->exception_end();
    610          SuperI != SuperE; ++SuperI) {
    611       QualType CanonicalSuperT = Context.getCanonicalType(*SuperI);
    612       // SubT must be SuperT or derived from it, or pointer or reference to
    613       // such types.
    614       if (const ReferenceType *RefTy = CanonicalSuperT->getAs<ReferenceType>())
    615         CanonicalSuperT = RefTy->getPointeeType();
    616       if (SubIsPointer) {
    617         if (const PointerType *PtrTy = CanonicalSuperT->getAs<PointerType>())
    618           CanonicalSuperT = PtrTy->getPointeeType();
    619         else {
    620           continue;
    621         }
    622       }
    623       CanonicalSuperT = CanonicalSuperT.getLocalUnqualifiedType();
    624       // If the types are the same, move on to the next type in the subset.
    625       if (CanonicalSubT == CanonicalSuperT) {
    626         Contained = true;
    627         break;
    628       }
    629 
    630       // Otherwise we need to check the inheritance.
    631       if (!SubIsClass || !CanonicalSuperT->isRecordType())
    632         continue;
    633 
    634       Paths.clear();
    635       if (!IsDerivedFrom(CanonicalSubT, CanonicalSuperT, Paths))
    636         continue;
    637 
    638       if (Paths.isAmbiguous(Context.getCanonicalType(CanonicalSuperT)))
    639         continue;
    640 
    641       // Do this check from a context without privileges.
    642       switch (CheckBaseClassAccess(SourceLocation(),
    643                                    CanonicalSuperT, CanonicalSubT,
    644                                    Paths.front(),
    645                                    /*Diagnostic*/ 0,
    646                                    /*ForceCheck*/ true,
    647                                    /*ForceUnprivileged*/ true)) {
    648       case AR_accessible: break;
    649       case AR_inaccessible: continue;
    650       case AR_dependent:
    651         llvm_unreachable("access check dependent for unprivileged context");
    652       case AR_delayed:
    653         llvm_unreachable("access check delayed in non-declaration");
    654       }
    655 
    656       Contained = true;
    657       break;
    658     }
    659     if (!Contained) {
    660       Diag(SubLoc, DiagID);
    661       if (NoteID.getDiagID() != 0)
    662         Diag(SuperLoc, NoteID);
    663       return true;
    664     }
    665   }
    666   // We've run half the gauntlet.
    667   return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
    668 }
    669 
    670 static bool CheckSpecForTypesEquivalent(Sema &S,
    671     const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
    672     QualType Target, SourceLocation TargetLoc,
    673     QualType Source, SourceLocation SourceLoc)
    674 {
    675   const FunctionProtoType *TFunc = GetUnderlyingFunction(Target);
    676   if (!TFunc)
    677     return false;
    678   const FunctionProtoType *SFunc = GetUnderlyingFunction(Source);
    679   if (!SFunc)
    680     return false;
    681 
    682   return S.CheckEquivalentExceptionSpec(DiagID, NoteID, TFunc, TargetLoc,
    683                                         SFunc, SourceLoc);
    684 }
    685 
    686 /// CheckParamExceptionSpec - Check if the parameter and return types of the
    687 /// two functions have equivalent exception specs. This is part of the
    688 /// assignment and override compatibility check. We do not check the parameters
    689 /// of parameter function pointers recursively, as no sane programmer would
    690 /// even be able to write such a function type.
    691 bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID,
    692     const FunctionProtoType *Target, SourceLocation TargetLoc,
    693     const FunctionProtoType *Source, SourceLocation SourceLoc)
    694 {
    695   if (CheckSpecForTypesEquivalent(*this,
    696                            PDiag(diag::err_deep_exception_specs_differ) << 0,
    697                                   PDiag(),
    698                                   Target->getResultType(), TargetLoc,
    699                                   Source->getResultType(), SourceLoc))
    700     return true;
    701 
    702   // We shouldn't even be testing this unless the arguments are otherwise
    703   // compatible.
    704   assert(Target->getNumArgs() == Source->getNumArgs() &&
    705          "Functions have different argument counts.");
    706   for (unsigned i = 0, E = Target->getNumArgs(); i != E; ++i) {
    707     if (CheckSpecForTypesEquivalent(*this,
    708                            PDiag(diag::err_deep_exception_specs_differ) << 1,
    709                                     PDiag(),
    710                                     Target->getArgType(i), TargetLoc,
    711                                     Source->getArgType(i), SourceLoc))
    712       return true;
    713   }
    714   return false;
    715 }
    716 
    717 bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType)
    718 {
    719   // First we check for applicability.
    720   // Target type must be a function, function pointer or function reference.
    721   const FunctionProtoType *ToFunc = GetUnderlyingFunction(ToType);
    722   if (!ToFunc)
    723     return false;
    724 
    725   // SourceType must be a function or function pointer.
    726   const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType());
    727   if (!FromFunc)
    728     return false;
    729 
    730   // Now we've got the correct types on both sides, check their compatibility.
    731   // This means that the source of the conversion can only throw a subset of
    732   // the exceptions of the target, and any exception specs on arguments or
    733   // return types must be equivalent.
    734   return CheckExceptionSpecSubset(PDiag(diag::err_incompatible_exception_specs),
    735                                   PDiag(), ToFunc,
    736                                   From->getSourceRange().getBegin(),
    737                                   FromFunc, SourceLocation());
    738 }
    739 
    740 bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
    741                                                 const CXXMethodDecl *Old) {
    742   if (getLangOpts().CPlusPlus0x && isa<CXXDestructorDecl>(New)) {
    743     // Don't check uninstantiated template destructors at all. We can only
    744     // synthesize correct specs after the template is instantiated.
    745     if (New->getParent()->isDependentType())
    746       return false;
    747     if (New->getParent()->isBeingDefined()) {
    748       // The destructor might be updated once the definition is finished. So
    749       // remember it and check later.
    750       DelayedDestructorExceptionSpecChecks.push_back(std::make_pair(
    751         cast<CXXDestructorDecl>(New), cast<CXXDestructorDecl>(Old)));
    752       return false;
    753     }
    754   }
    755   unsigned DiagID = diag::err_override_exception_spec;
    756   if (getLangOpts().MicrosoftExt)
    757     DiagID = diag::warn_override_exception_spec;
    758   return CheckExceptionSpecSubset(PDiag(DiagID),
    759                                   PDiag(diag::note_overridden_virtual_function),
    760                                   Old->getType()->getAs<FunctionProtoType>(),
    761                                   Old->getLocation(),
    762                                   New->getType()->getAs<FunctionProtoType>(),
    763                                   New->getLocation());
    764 }
    765 
    766 static CanThrowResult canSubExprsThrow(Sema &S, const Expr *CE) {
    767   Expr *E = const_cast<Expr*>(CE);
    768   CanThrowResult R = CT_Cannot;
    769   for (Expr::child_range I = E->children(); I && R != CT_Can; ++I)
    770     R = mergeCanThrow(R, S.canThrow(cast<Expr>(*I)));
    771   return R;
    772 }
    773 
    774 static CanThrowResult canCalleeThrow(Sema &S, const Expr *E,
    775                                            const Decl *D,
    776                                            bool NullThrows = true) {
    777   if (!D)
    778     return NullThrows ? CT_Can : CT_Cannot;
    779 
    780   // See if we can get a function type from the decl somehow.
    781   const ValueDecl *VD = dyn_cast<ValueDecl>(D);
    782   if (!VD) // If we have no clue what we're calling, assume the worst.
    783     return CT_Can;
    784 
    785   // As an extension, we assume that __attribute__((nothrow)) functions don't
    786   // throw.
    787   if (isa<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>())
    788     return CT_Cannot;
    789 
    790   QualType T = VD->getType();
    791   const FunctionProtoType *FT;
    792   if ((FT = T->getAs<FunctionProtoType>())) {
    793   } else if (const PointerType *PT = T->getAs<PointerType>())
    794     FT = PT->getPointeeType()->getAs<FunctionProtoType>();
    795   else if (const ReferenceType *RT = T->getAs<ReferenceType>())
    796     FT = RT->getPointeeType()->getAs<FunctionProtoType>();
    797   else if (const MemberPointerType *MT = T->getAs<MemberPointerType>())
    798     FT = MT->getPointeeType()->getAs<FunctionProtoType>();
    799   else if (const BlockPointerType *BT = T->getAs<BlockPointerType>())
    800     FT = BT->getPointeeType()->getAs<FunctionProtoType>();
    801 
    802   if (!FT)
    803     return CT_Can;
    804 
    805   FT = S.ResolveExceptionSpec(E->getLocStart(), FT);
    806   if (!FT)
    807     return CT_Can;
    808 
    809   if (FT->getExceptionSpecType() == EST_Delayed) {
    810     // FIXME: Try to resolve a delayed exception spec in ResolveExceptionSpec.
    811     assert(isa<CXXConstructorDecl>(D) &&
    812            "only constructor exception specs can be unknown");
    813     S.Diag(E->getLocStart(), diag::err_exception_spec_unknown)
    814       << E->getSourceRange();
    815     return CT_Can;
    816   }
    817 
    818   return FT->isNothrow(S.Context) ? CT_Cannot : CT_Can;
    819 }
    820 
    821 static CanThrowResult canDynamicCastThrow(const CXXDynamicCastExpr *DC) {
    822   if (DC->isTypeDependent())
    823     return CT_Dependent;
    824 
    825   if (!DC->getTypeAsWritten()->isReferenceType())
    826     return CT_Cannot;
    827 
    828   if (DC->getSubExpr()->isTypeDependent())
    829     return CT_Dependent;
    830 
    831   return DC->getCastKind() == clang::CK_Dynamic? CT_Can : CT_Cannot;
    832 }
    833 
    834 static CanThrowResult canTypeidThrow(Sema &S, const CXXTypeidExpr *DC) {
    835   if (DC->isTypeOperand())
    836     return CT_Cannot;
    837 
    838   Expr *Op = DC->getExprOperand();
    839   if (Op->isTypeDependent())
    840     return CT_Dependent;
    841 
    842   const RecordType *RT = Op->getType()->getAs<RecordType>();
    843   if (!RT)
    844     return CT_Cannot;
    845 
    846   if (!cast<CXXRecordDecl>(RT->getDecl())->isPolymorphic())
    847     return CT_Cannot;
    848 
    849   if (Op->Classify(S.Context).isPRValue())
    850     return CT_Cannot;
    851 
    852   return CT_Can;
    853 }
    854 
    855 CanThrowResult Sema::canThrow(const Expr *E) {
    856   // C++ [expr.unary.noexcept]p3:
    857   //   [Can throw] if in a potentially-evaluated context the expression would
    858   //   contain:
    859   switch (E->getStmtClass()) {
    860   case Expr::CXXThrowExprClass:
    861     //   - a potentially evaluated throw-expression
    862     return CT_Can;
    863 
    864   case Expr::CXXDynamicCastExprClass: {
    865     //   - a potentially evaluated dynamic_cast expression dynamic_cast<T>(v),
    866     //     where T is a reference type, that requires a run-time check
    867     CanThrowResult CT = canDynamicCastThrow(cast<CXXDynamicCastExpr>(E));
    868     if (CT == CT_Can)
    869       return CT;
    870     return mergeCanThrow(CT, canSubExprsThrow(*this, E));
    871   }
    872 
    873   case Expr::CXXTypeidExprClass:
    874     //   - a potentially evaluated typeid expression applied to a glvalue
    875     //     expression whose type is a polymorphic class type
    876     return canTypeidThrow(*this, cast<CXXTypeidExpr>(E));
    877 
    878     //   - a potentially evaluated call to a function, member function, function
    879     //     pointer, or member function pointer that does not have a non-throwing
    880     //     exception-specification
    881   case Expr::CallExprClass:
    882   case Expr::CXXMemberCallExprClass:
    883   case Expr::CXXOperatorCallExprClass:
    884   case Expr::UserDefinedLiteralClass: {
    885     const CallExpr *CE = cast<CallExpr>(E);
    886     CanThrowResult CT;
    887     if (E->isTypeDependent())
    888       CT = CT_Dependent;
    889     else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens()))
    890       CT = CT_Cannot;
    891     else
    892       CT = canCalleeThrow(*this, E, CE->getCalleeDecl());
    893     if (CT == CT_Can)
    894       return CT;
    895     return mergeCanThrow(CT, canSubExprsThrow(*this, E));
    896   }
    897 
    898   case Expr::CXXConstructExprClass:
    899   case Expr::CXXTemporaryObjectExprClass: {
    900     CanThrowResult CT = canCalleeThrow(*this, E,
    901         cast<CXXConstructExpr>(E)->getConstructor());
    902     if (CT == CT_Can)
    903       return CT;
    904     return mergeCanThrow(CT, canSubExprsThrow(*this, E));
    905   }
    906 
    907   case Expr::LambdaExprClass: {
    908     const LambdaExpr *Lambda = cast<LambdaExpr>(E);
    909     CanThrowResult CT = CT_Cannot;
    910     for (LambdaExpr::capture_init_iterator Cap = Lambda->capture_init_begin(),
    911                                         CapEnd = Lambda->capture_init_end();
    912          Cap != CapEnd; ++Cap)
    913       CT = mergeCanThrow(CT, canThrow(*Cap));
    914     return CT;
    915   }
    916 
    917   case Expr::CXXNewExprClass: {
    918     CanThrowResult CT;
    919     if (E->isTypeDependent())
    920       CT = CT_Dependent;
    921     else
    922       CT = canCalleeThrow(*this, E, cast<CXXNewExpr>(E)->getOperatorNew());
    923     if (CT == CT_Can)
    924       return CT;
    925     return mergeCanThrow(CT, canSubExprsThrow(*this, E));
    926   }
    927 
    928   case Expr::CXXDeleteExprClass: {
    929     CanThrowResult CT;
    930     QualType DTy = cast<CXXDeleteExpr>(E)->getDestroyedType();
    931     if (DTy.isNull() || DTy->isDependentType()) {
    932       CT = CT_Dependent;
    933     } else {
    934       CT = canCalleeThrow(*this, E,
    935                           cast<CXXDeleteExpr>(E)->getOperatorDelete());
    936       if (const RecordType *RT = DTy->getAs<RecordType>()) {
    937         const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
    938         CT = mergeCanThrow(CT, canCalleeThrow(*this, E, RD->getDestructor()));
    939       }
    940       if (CT == CT_Can)
    941         return CT;
    942     }
    943     return mergeCanThrow(CT, canSubExprsThrow(*this, E));
    944   }
    945 
    946   case Expr::CXXBindTemporaryExprClass: {
    947     // The bound temporary has to be destroyed again, which might throw.
    948     CanThrowResult CT = canCalleeThrow(*this, E,
    949       cast<CXXBindTemporaryExpr>(E)->getTemporary()->getDestructor());
    950     if (CT == CT_Can)
    951       return CT;
    952     return mergeCanThrow(CT, canSubExprsThrow(*this, E));
    953   }
    954 
    955     // ObjC message sends are like function calls, but never have exception
    956     // specs.
    957   case Expr::ObjCMessageExprClass:
    958   case Expr::ObjCPropertyRefExprClass:
    959   case Expr::ObjCSubscriptRefExprClass:
    960     return CT_Can;
    961 
    962     // All the ObjC literals that are implemented as calls are
    963     // potentially throwing unless we decide to close off that
    964     // possibility.
    965   case Expr::ObjCArrayLiteralClass:
    966   case Expr::ObjCDictionaryLiteralClass:
    967   case Expr::ObjCBoxedExprClass:
    968     return CT_Can;
    969 
    970     // Many other things have subexpressions, so we have to test those.
    971     // Some are simple:
    972   case Expr::ConditionalOperatorClass:
    973   case Expr::CompoundLiteralExprClass:
    974   case Expr::CXXConstCastExprClass:
    975   case Expr::CXXDefaultArgExprClass:
    976   case Expr::CXXReinterpretCastExprClass:
    977   case Expr::DesignatedInitExprClass:
    978   case Expr::ExprWithCleanupsClass:
    979   case Expr::ExtVectorElementExprClass:
    980   case Expr::InitListExprClass:
    981   case Expr::MemberExprClass:
    982   case Expr::ObjCIsaExprClass:
    983   case Expr::ObjCIvarRefExprClass:
    984   case Expr::ParenExprClass:
    985   case Expr::ParenListExprClass:
    986   case Expr::ShuffleVectorExprClass:
    987   case Expr::VAArgExprClass:
    988     return canSubExprsThrow(*this, E);
    989 
    990     // Some might be dependent for other reasons.
    991   case Expr::ArraySubscriptExprClass:
    992   case Expr::BinaryOperatorClass:
    993   case Expr::CompoundAssignOperatorClass:
    994   case Expr::CStyleCastExprClass:
    995   case Expr::CXXStaticCastExprClass:
    996   case Expr::CXXFunctionalCastExprClass:
    997   case Expr::ImplicitCastExprClass:
    998   case Expr::MaterializeTemporaryExprClass:
    999   case Expr::UnaryOperatorClass: {
   1000     CanThrowResult CT = E->isTypeDependent() ? CT_Dependent : CT_Cannot;
   1001     return mergeCanThrow(CT, canSubExprsThrow(*this, E));
   1002   }
   1003 
   1004     // FIXME: We should handle StmtExpr, but that opens a MASSIVE can of worms.
   1005   case Expr::StmtExprClass:
   1006     return CT_Can;
   1007 
   1008   case Expr::ChooseExprClass:
   1009     if (E->isTypeDependent() || E->isValueDependent())
   1010       return CT_Dependent;
   1011     return canThrow(cast<ChooseExpr>(E)->getChosenSubExpr(Context));
   1012 
   1013   case Expr::GenericSelectionExprClass:
   1014     if (cast<GenericSelectionExpr>(E)->isResultDependent())
   1015       return CT_Dependent;
   1016     return canThrow(cast<GenericSelectionExpr>(E)->getResultExpr());
   1017 
   1018     // Some expressions are always dependent.
   1019   case Expr::CXXDependentScopeMemberExprClass:
   1020   case Expr::CXXUnresolvedConstructExprClass:
   1021   case Expr::DependentScopeDeclRefExprClass:
   1022     return CT_Dependent;
   1023 
   1024   case Expr::AsTypeExprClass:
   1025   case Expr::BinaryConditionalOperatorClass:
   1026   case Expr::BlockExprClass:
   1027   case Expr::CUDAKernelCallExprClass:
   1028   case Expr::DeclRefExprClass:
   1029   case Expr::ObjCBridgedCastExprClass:
   1030   case Expr::ObjCIndirectCopyRestoreExprClass:
   1031   case Expr::ObjCProtocolExprClass:
   1032   case Expr::ObjCSelectorExprClass:
   1033   case Expr::OffsetOfExprClass:
   1034   case Expr::PackExpansionExprClass:
   1035   case Expr::PseudoObjectExprClass:
   1036   case Expr::SubstNonTypeTemplateParmExprClass:
   1037   case Expr::SubstNonTypeTemplateParmPackExprClass:
   1038   case Expr::UnaryExprOrTypeTraitExprClass:
   1039   case Expr::UnresolvedLookupExprClass:
   1040   case Expr::UnresolvedMemberExprClass:
   1041     // FIXME: Can any of the above throw?  If so, when?
   1042     return CT_Cannot;
   1043 
   1044   case Expr::AddrLabelExprClass:
   1045   case Expr::ArrayTypeTraitExprClass:
   1046   case Expr::AtomicExprClass:
   1047   case Expr::BinaryTypeTraitExprClass:
   1048   case Expr::TypeTraitExprClass:
   1049   case Expr::CXXBoolLiteralExprClass:
   1050   case Expr::CXXNoexceptExprClass:
   1051   case Expr::CXXNullPtrLiteralExprClass:
   1052   case Expr::CXXPseudoDestructorExprClass:
   1053   case Expr::CXXScalarValueInitExprClass:
   1054   case Expr::CXXThisExprClass:
   1055   case Expr::CXXUuidofExprClass:
   1056   case Expr::CharacterLiteralClass:
   1057   case Expr::ExpressionTraitExprClass:
   1058   case Expr::FloatingLiteralClass:
   1059   case Expr::GNUNullExprClass:
   1060   case Expr::ImaginaryLiteralClass:
   1061   case Expr::ImplicitValueInitExprClass:
   1062   case Expr::IntegerLiteralClass:
   1063   case Expr::ObjCEncodeExprClass:
   1064   case Expr::ObjCStringLiteralClass:
   1065   case Expr::ObjCBoolLiteralExprClass:
   1066   case Expr::OpaqueValueExprClass:
   1067   case Expr::PredefinedExprClass:
   1068   case Expr::SizeOfPackExprClass:
   1069   case Expr::StringLiteralClass:
   1070   case Expr::UnaryTypeTraitExprClass:
   1071     // These expressions can never throw.
   1072     return CT_Cannot;
   1073 
   1074 #define STMT(CLASS, PARENT) case Expr::CLASS##Class:
   1075 #define STMT_RANGE(Base, First, Last)
   1076 #define LAST_STMT_RANGE(BASE, FIRST, LAST)
   1077 #define EXPR(CLASS, PARENT)
   1078 #define ABSTRACT_STMT(STMT)
   1079 #include "clang/AST/StmtNodes.inc"
   1080   case Expr::NoStmtClass:
   1081     llvm_unreachable("Invalid class for expression");
   1082   }
   1083   llvm_unreachable("Bogus StmtClass");
   1084 }
   1085 
   1086 } // end namespace clang
   1087