[PATCH] Add getter methods for arguments, ranges and fix-it hints to PartialDiagnostic

Stephan Tolksdorf st at quanttec.com
Wed Mar 12 11:11:50 PDT 2014


Hi rsmith,

Add getter methods for arguments, ranges and fix-it hints to PartialDiagnostic

I copied the methods from Diagnostic.h and adapted them to the different storage. I've also modified getFixItHints to return an ArrayRef instead of a pointer.

I need the argument and range accessors for improving the enable-if SFINAE diagnostics.

http://llvm-reviews.chandlerc.com/D3060

Files:
  include/clang/Basic/PartialDiagnostic.h
  unittests/Basic/CMakeLists.txt
  unittests/Basic/PartialDiagnosticTest.cpp

Index: include/clang/Basic/PartialDiagnostic.h
===================================================================
--- include/clang/Basic/PartialDiagnostic.h
+++ include/clang/Basic/PartialDiagnostic.h
@@ -272,6 +272,89 @@
 
   unsigned getDiagID() const { return DiagID; }
 
+  /// \brief Return the number of arguments (excluding source ranges or fix-it
+  /// hints) stored for this diagnostic.
+  unsigned getNumArgs() const {
+    return DiagStorage ? DiagStorage->NumDiagArgs : 0;
+  }
+
+  /// \brief Return the kind of the specified index.
+  ///
+  /// Based on the kind of argument, the accessors below can be used to get
+  /// the value.
+  ///
+  /// \pre Idx < getNumArgs()
+  DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const {
+    assert(Idx < getNumArgs() && "Argument index out of range!");
+    return (DiagnosticsEngine::ArgumentKind)DiagStorage->DiagArgumentsKind[Idx];
+  }
+
+  /// \brief Return the provided argument string specified by \p Idx.
+  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_std_string
+  const std::string &getArgStdStr(unsigned Idx) const {
+    assert(getArgKind(Idx) == DiagnosticsEngine::ak_std_string &&
+           "invalid argument accessor!");
+    return DiagStorage->DiagArgumentsStr[Idx];
+  }
+
+  /// \brief Return the specified C string argument.
+  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_c_string
+  const char *getArgCStr(unsigned Idx) const {
+    assert(getArgKind(Idx) == DiagnosticsEngine::ak_c_string &&
+           "invalid argument accessor!");
+    return reinterpret_cast<const char *>(DiagStorage->DiagArgumentsVal[Idx]);
+  }
+
+  /// \brief Return the specified signed integer argument.
+  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_sint
+  int getArgSInt(unsigned Idx) const {
+    assert(getArgKind(Idx) == DiagnosticsEngine::ak_sint &&
+           "invalid argument accessor!");
+    return (int)DiagStorage->DiagArgumentsVal[Idx];
+  }
+
+  /// \brief Return the specified unsigned integer argument.
+  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_uint
+  unsigned getArgUInt(unsigned Idx) const {
+    assert(getArgKind(Idx) == DiagnosticsEngine::ak_uint &&
+           "invalid argument accessor!");
+    return (unsigned)DiagStorage->DiagArgumentsVal[Idx];
+  }
+
+  /// \brief Return the specified IdentifierInfo argument.
+  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo
+  const IdentifierInfo *getArgIdentifier(unsigned Idx) const {
+    assert(getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo &&
+           "invalid argument accessor!");
+    return reinterpret_cast<IdentifierInfo *>(
+        DiagStorage->DiagArgumentsVal[Idx]);
+  }
+
+  /// \brief Return the specified non-string argument in an opaque form.
+  /// \pre getArgKind(Idx) != DiagnosticsEngine::ak_std_string
+  intptr_t getRawArg(unsigned Idx) const {
+    assert(getArgKind(Idx) != DiagnosticsEngine::ak_std_string &&
+           "invalid argument accessor!");
+    return DiagStorage->DiagArgumentsVal[Idx];
+  }
+
+  /// \brief Return an array reference for this diagnostic's ranges.
+  /// The returned array reference gets invalidated if this diagnostics's
+  /// storage is reset.
+  ArrayRef<CharSourceRange> getRanges() const {
+    return !DiagStorage ? ArrayRef<CharSourceRange>()
+                        : llvm::makeArrayRef(DiagStorage->DiagRanges,
+                                             DiagStorage->NumDiagRanges);
+  }
+
+  /// \brief Return an array reference for this diagnostic's fix-it hints.
+  ///
+  /// The returned array reference gets invalidated if another fix-it hint is
+  /// added to the diagnostic or if this diagnostics's storage is reset.
+  ArrayRef<FixItHint> getFixItHints() const {
+    return DiagStorage ? DiagStorage->FixItHints : ArrayRef<FixItHint>();
+  }
+
   void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const {
     if (!DiagStorage)
       DiagStorage = getStorage();
Index: unittests/Basic/CMakeLists.txt
===================================================================
--- unittests/Basic/CMakeLists.txt
+++ unittests/Basic/CMakeLists.txt
@@ -5,6 +5,7 @@
 add_clang_unittest(BasicTests
   CharInfoTest.cpp
   FileManagerTest.cpp
+  PartialDiagnosticTest.cpp
   SourceManagerTest.cpp
   VirtualFileSystemTest.cpp
   )
Index: unittests/Basic/PartialDiagnosticTest.cpp
===================================================================
--- /dev/null
+++ unittests/Basic/PartialDiagnosticTest.cpp
@@ -0,0 +1,59 @@
+//===- unittests/Basic/PartialDiagnostic.cpp -- PartialDiagnostic tests ---===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace clang;
+
+TEST(PartialDiagnosticTest, getAccessors) {
+  PartialDiagnostic::StorageAllocator Allocator;
+
+  PartialDiagnostic PD(1, Allocator);
+  EXPECT_EQ(PD.getNumArgs(), 0);
+  EXPECT_EQ(PD.getRanges().size(), 0);
+  EXPECT_EQ(PD.getFixItHints().size(), 0);
+  EXPECT_TRUE(!PD.hasStorage());
+
+  PD << -1;
+  EXPECT_TRUE(PD.hasStorage());
+  EXPECT_EQ(PD.getNumArgs(), 1);
+  EXPECT_EQ(PD.getArgKind(0), DiagnosticsEngine::ak_sint);
+  EXPECT_EQ(PD.getArgSInt(0), -1);
+
+  PD << 2u;
+  EXPECT_EQ(PD.getArgUInt(1), 2);
+
+  std::string Str("std::string");
+  PD << Str;
+  EXPECT_EQ(PD.getArgStdStr(2), Str);
+
+  const char *CStr("C-string");
+  PD << CStr;
+  EXPECT_TRUE((const void *)PD.getArgCStr(3) == (const void *)CStr);
+
+  IdentifierInfo II;
+  PD << &II;
+  EXPECT_TRUE(PD.getArgIdentifier(4) == &II);
+  EXPECT_TRUE(PD.getRawArg(4) == (intptr_t)&II);
+
+  SourceLocation Loc1 = SourceLocation::getFromRawEncoding(1);
+  SourceLocation Loc2 = SourceLocation::getFromRawEncoding(2);
+  CharSourceRange Range(SourceRange(Loc1, Loc2), false);
+  PD << Range;
+  EXPECT_EQ(PD.getRanges().size(), 1);
+  EXPECT_EQ(PD.getRanges()[0].getAsRange(), Range.getAsRange());
+
+  FixItHint Hint = FixItHint::CreateInsertion(Loc1, "Insert");
+  PD << Hint;
+  EXPECT_EQ(PD.getFixItHints().size(), 1);
+  EXPECT_EQ(PD.getFixItHints()[0].CodeToInsert, "Insert");
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D3060.1.patch
Type: text/x-patch
Size: 6389 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140312/09b9ce61/attachment.bin>


More information about the cfe-commits mailing list