51

I am working on a c++ project where I am using a lot of #pragma omp. I use the wonderful clang-format for tidiness but it always deletes the indentation for all preprocessor directives. Is there a way to change that behavior? Or is there another formatting tool that is more recommendable? Or should I avoid using these tools at all?

5
  • 2
    Historically, preprocessor directives had to start at the first column, and it's still customary for many to place at least the leading # directive marker in the first column of the line. Commented Jun 29, 2014 at 12:52
  • 5
    I understand... but you see my point, don't you? Since "#pragma omp" is applied to blocks (which are indented) it is much more pleasant to see especially these directives indented as well... Commented Jun 29, 2014 at 14:05
  • 3
    I have the same problem. All I could find was an open bug report. I hope they will implement this soon. Commented Jun 8, 2015 at 12:43
  • I didn't know about the bug report. But they seem to be aware of the issue which is something :) With the upcoming OpenMP feature in clang I am sure this will gain some momentum... Commented Jun 28, 2015 at 9:05
  • There are two relevant open bug reports: 36019 and 36020 Commented Sep 7, 2018 at 12:57

5 Answers 5

28

As of version 6.0, the option IndentPPDirectives can be used. Usage is described in this review.

Using IndentPPDirectives: None results in:

#if FOO
#if BAR
#include <foo>
#endif
#endif

While IndentPPDirectives: AfterHash gives:

#if FOO
#  if BAR
#    include <foo>
#  endif
#endif

Edit: see @Gabriel Staples' answer for details on the BeforeHash option introduced in clang-format version 9.

Sign up to request clarification or add additional context in comments.

3 Comments

As far as I can tell (from trying) this will not indent to # pragma omp... to match the surrounding code. Instead it will just indent according to the level at which the statement is nested inside other directives, such as the #if you show.
There's now a IndentPPDirectives: BeforeHash option too! See my answer here: stackoverflow.com/a/66004745/4561887.
Note: here's the Clang-format version 6 documentation: releases.llvm.org/6.0.0/tools/clang/docs/…. The latest documentation (currently version 12) can always be found here: clang.llvm.org/docs/ClangFormatStyleOptions.html.
8

By manual inspection of the various Clang-Format Style Options pages, I have determined that as of Clang-format version 9, a 3rd (and best, in my opinion) option came out, called BeforeHash.

Note: as of the time of this writing, Clang 12 is out. For the latest Clang-format options documentation for whatever version is currently out, see here: https://clang.llvm.org/docs/ClangFormatStyleOptions.html.

In your .clang-format file, you can therefore specify 3 options, as follows:

1. No indenting

IndentPPDirectives: None

Example:

#if FOO
#if BAR
#include <foo>
#endif
#endif

2. Indent after the hash (#)

IndentPPDirectives: AfterHash

Example:

#if FOO
#  if BAR
#    include <foo>
#  endif
#endif

3. (Newest and best option in my opinion--available as of Clang-Format version 9) Indent before the hash (#)

IndentPPDirectives: BeforeHash

Example:

#if FOO
  #if BAR
    #include <foo>
  #endif
#endif

How to install the latest version of clang-format on Ubuntu

...so that you can get access to the version 9 or later feature just above:

See my detailed instructions here. The latest version at this moment is 14.0.0.

References

  1. For all this documentation, as well as for the source of the exact examples I have used above, see the IndentPPDirectives section of the LLVM Clang-format Style Options official documentation here: https://clang.llvm.org/docs/ClangFormatStyleOptions.html.

See also

  1. My answer: How to install the latest version of clang-format and git-clang-format (runnable as git clang-format)
  2. My clang-format-based project here: eRCaGuy_CodeFormatter

Comments

6

You might want to just patch it yourself and make a pull request.

It's not that hard, I made a similarly mundane pull request once. The clang-format code is pretty tidy. Clang-format already handles code comments in the way that you want, aligning them to the surrounding code (at least it has an option to enable this) so making a patch to treat certain PP directives the same way should be straightforward.

Alternatively, you can just write the patch yourself and compile clang yourself from source with the extra option, for use in your project. I also did this before I decided to send them the patch.

It seriously took me only a few hours to figure out how to do this, their code is much cleaner than the code of many other open source projects.

3 Comments

I will look into it and if it's really not that hard I will do it. But right now I'm drowning in work, so maybe in 2 or 3 months...
have you made some progress on this`? :-) highly appreciated feature!
"Alternatively, you can just write the patch yourself and compile clang yourself from source with the extra option, for use in your project. I also did this before I decided to send them the patch." So where is the patch?
5

It's been late but this is the solution you are looking for. It formats the pragma along with the code block. You can use this before they finally support the pragma indentation.

https://github.com/MedicineYeh/p-clang-format

The main concept is replacing the string so that the formatter uses the "correct" rules on these pragmas. The motivative example is as following.

# Replace "#pragma omp" by "//#pragma omp"
sed -i 's/#pragma omp/\/\/#pragma omp/g' ./main.c
# Do format
clang-format ./main.c
# Replace "// *#pragma omp" by "#pragma omp"
sed -i 's/\/\/ *#pragma omp/#pragma omp/g' ./main.c

3 Comments

Good answer, as long as your code doesn't have any already-commented-out #pragmas that become re-enabled by this. If your code does have them, #pragma omp can be replaced by something like // AWRBHAWRBWAQ instead. Pretty much any comment will do as long as it's not already present in the source code.
If a #pragma is already commented out, this will comment it out again, then revert it after clang-format. //#pragma omp becomes ////#pragma omp, then the second sed reverts it to //#pragma omp. However, in the second sed, I don't see any reason to match spaces using \/\/ *#pragma instead of \/\/#pragma. Also the /g seems unnecessary, as there will be only one #pragma per line. So I would do sed -i 's/\/\/#pragma omp/#pragma omp/'
You need clang-format -i ./main.c to do edits in-place, right?
1

astyle (Artistic Style) indents #pragma omp nicely with the code, out-of-the-box. There doesn't even seem to be an option to change the behavior. Only line continuations aren't indented, as shown in the example—I would prefer line continuations were indented, perhaps 8 spaces, under omp. Other pragmas are aligned left.

void foo()
{
        #pragma omp parallel
#pragma omp master
    {
#pragma omp task depend( some_expression ) \
            depend( other_expression ) \
    priority(1)
        {
            code();
        }
    }

    #pragma other
    code();
}

becomes

void foo()
{
    #pragma omp parallel
    #pragma omp master
    {
        #pragma omp task depend( some_expression ) \
        depend( other_expression ) \
        priority(1)
        {
            code();
        }
    }

#pragma other
    code();
}

There is an Astyle Visual Studio extension.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.