diff options
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.def | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/Sema.h | 6 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 25 | ||||
| -rw-r--r-- | clang/test/SemaObjC/protocol-forward-circular.m | 10 | 
4 files changed, 43 insertions, 0 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.def b/clang/include/clang/Basic/DiagnosticSemaKinds.def index 6f94d8e2ec3..2d751ad8afb 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.def +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.def @@ -135,6 +135,8 @@ DIAG(warn_undef_interface, WARNING,       "cannot find interface declaration for %0")  DIAG(err_duplicate_protocol_def, ERROR,       "duplicate protocol definition of %0") +DIAG(err_protocol_has_circular_dependency, ERROR, +     "protocol has circular dependency")  DIAG(err_undeclared_protocol, ERROR,       "cannot find protocol declaration for %0")  DIAG(warn_undef_protocolref, WARNING, diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index de9b4cd013a..d7d80638d19 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -25,6 +25,7 @@  #include "llvm/ADT/DenseSet.h"  #include "llvm/ADT/SmallPtrSet.h"  #include "llvm/ADT/OwningPtr.h" +#include "clang/AST/DeclObjC.h"  #include <string>  #include <vector> @@ -1678,6 +1679,11 @@ public:                      SourceLocation AtCompatibilityAliasLoc,                      IdentifierInfo *AliasName,  SourceLocation AliasLocation,                      IdentifierInfo *ClassName, SourceLocation ClassLocation); + +  void CheckForwardProtocolDeclarationForCircularDependency( +    IdentifierInfo *PName, +    SourceLocation &PLoc, SourceLocation PrevLoc, +    const ObjCList<ObjCProtocolDecl> &PList);    virtual DeclTy *ActOnStartProtocolInterface(                      SourceLocation AtProtoInterfaceLoc, diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 55b0d16e8c4..d90f2adc77a 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -215,6 +215,25 @@ Sema::DeclTy *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc,    return AliasDecl;  } +void Sema::CheckForwardProtocolDeclarationForCircularDependency( +  IdentifierInfo *PName, +  SourceLocation &Ploc, SourceLocation PrevLoc, +  const ObjCList<ObjCProtocolDecl> &PList)  +{ +  for (ObjCList<ObjCProtocolDecl>::iterator I = PList.begin(), +       E = PList.end(); I != E; ++I) { +        +    if (ObjCProtocolDecl *PDecl = ObjCProtocols[(*I)->getIdentifier()]) { +      if (PDecl->getIdentifier() == PName) { +        Diag(Ploc, diag::err_protocol_has_circular_dependency); +        Diag(PrevLoc, diag::note_previous_definition); +      } +      CheckForwardProtocolDeclarationForCircularDependency(PName, Ploc,  +        PDecl->getLocation(), PDecl->getReferencedProtocols()); +    } +  } +} +  Sema::DeclTy *  Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,                                    IdentifierInfo *ProtocolName, @@ -236,6 +255,12 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,        // FIXME: don't leak the objects passed in!        return PDecl;      } +    ObjCList<ObjCProtocolDecl> PList; +    PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context);  +    CheckForwardProtocolDeclarationForCircularDependency( +      ProtocolName, ProtocolLoc, PDecl->getLocation(), PList); +    PList.Destroy(Context); +          // Make sure the cached decl gets a valid start location.      PDecl->setLocation(AtProtoInterfaceLoc);      PDecl->setForwardDecl(false); diff --git a/clang/test/SemaObjC/protocol-forward-circular.m b/clang/test/SemaObjC/protocol-forward-circular.m new file mode 100644 index 00000000000..836d5b23507 --- /dev/null +++ b/clang/test/SemaObjC/protocol-forward-circular.m @@ -0,0 +1,10 @@ +// RUN: clang -fsyntax-only -verify %s + +@protocol B; +@protocol C < B > // expected-warning{{cannot find protocol definition for 'B'}} // expected-note{{previous definition is here}} +@end +@protocol A < C >  +@end +@protocol B < A > // expected-error{{protocol has circular dependency}} +@end +  | 

